From 4f3fa403469cc18913b4543f43d4bca7dea9537f Mon Sep 17 00:00:00 2001 From: L3odr0id Date: Wed, 27 Sep 2023 20:03:50 +0300 Subject: [PATCH 1/7] WIP: Multitransfer design --- assets/translations/en.json | 2 +- lib/core/theme/d3p_special_styles.dart | 2 +- lib/core/widgets/buttons/elevated_button.dart | 124 +++++---------- lib/core/widgets/buttons/enum_button.dart | 22 ++- .../input/textformfield/bottom_help_text.dart | 2 +- .../input/textformfield/textformfield.dart | 44 +++-- lib/core/widgets/slider/slider.dart | 8 +- .../create_account_mnemonic_confirm.dart | 5 +- .../create_account_wrapper.dart | 1 - .../bloc/transfer_info_cubit.dart | 44 ++++- .../bloc/transfer_info_cubit.g.dart | 31 +++- .../domain/entities/transfer_history_ui.dart | 2 +- .../balance_card/basic_balance_card.dart | 2 +- .../transfer_page/transfer_page.dart | 75 ++++++--- .../transfer_page/transfer_page_wrapper.dart | 2 - .../widgets/amount_textfield.dart | 16 +- .../widgets/basic_transfer_block.dart | 26 +++ .../widgets/basic_transfer_textfield.dart | 45 ++++++ .../widgets/from_address_textfield.dart | 150 ++++++++++++++++-- .../widgets/password_textfield.dart | 3 +- .../widgets/to_address_textfield.dart | 21 ++- .../widgets/transfer_type_dropdown.dart | 17 +- .../widgets/asset_balance_text.dart | 2 +- 23 files changed, 461 insertions(+), 185 deletions(-) create mode 100644 lib/features/wallet_screen/presentation/transfer_page/widgets/basic_transfer_block.dart create mode 100644 lib/features/wallet_screen/presentation/transfer_page/widgets/basic_transfer_textfield.dart diff --git a/assets/translations/en.json b/assets/translations/en.json index 80df0787..b79a338e 100644 --- a/assets/translations/en.json +++ b/assets/translations/en.json @@ -257,7 +257,7 @@ "to_address_hint": "Enter address", "amount_label": "Amount (Balance: {})", "amount_hint": "Enter amount", - "enter_password_hint": "password", + "enter_password_hint": "Password", "enter_password_label": "Your password", "existential_deposit_label": "existential deposit", "existential_deposit_text": "The minimum amount thath an account should have to be deemed active.", diff --git a/lib/core/theme/d3p_special_styles.dart b/lib/core/theme/d3p_special_styles.dart index a2e76543..b13be9b4 100644 --- a/lib/core/theme/d3p_special_styles.dart +++ b/lib/core/theme/d3p_special_styles.dart @@ -84,7 +84,7 @@ extension BodyCustomText on CustomTextStyles { themeData.textTheme.bodyLarge!.copyWith(color: _themeOpposite); TextStyle get d3pBodyMedium => themeData.textTheme.bodyMedium!.copyWith(color: _themeOpposite); - TextStyle get dp3BodySmall => + TextStyle get d3pBodySmall => themeData.textTheme.bodySmall!.copyWith(color: _themeOpposite); } diff --git a/lib/core/widgets/buttons/elevated_button.dart b/lib/core/widgets/buttons/elevated_button.dart index 10ffb178..ee1f4508 100644 --- a/lib/core/widgets/buttons/elevated_button.dart +++ b/lib/core/widgets/buttons/elevated_button.dart @@ -12,16 +12,24 @@ class D3pElevatedButton extends StatelessWidget { this.icon, this.backgroundColor, this.foregroundColor, + this.elevation, + this.childAlignment, + this.textStyle, + this.child, }) : super(key: key); final void Function()? onPressed; - final String text; + final String? text; final IconData? iconData; final Size? minimumSize; final EdgeInsets? padding; final Widget? icon; final Color? foregroundColor; final Color? backgroundColor; + final double? elevation; + final MainAxisAlignment? childAlignment; + final TextStyle? textStyle; + final Widget? child; @override Widget build(final BuildContext context) { @@ -31,23 +39,30 @@ class D3pElevatedButton extends StatelessWidget { child: PlatformElevatedButton( padding: padding ?? EdgeInsets.zero, onPressed: onPressed, - // material: (final context, final platform) => - // d3pElevatedTheme.resolveMaterial( - // text: text, - // icon: icon, - // iconData: iconData, - // ), - // cupertino: (final context, final _) => - // d3pElevatedTheme.resolveCupertino( - // context: context, - // text: text, - // icon: icon, - // iconData: iconData, - // ), - child: _ElevatedButtonChild( - icon: icon, - iconData: iconData, - text: text, + child: child ?? + _ElevatedButtonChild( + icon: icon, + iconData: iconData, + text: text ?? '', + childAlignment: childAlignment, + ), + // TODO CHECK CUPERTINO + material: (final context, final platform) => + MaterialElevatedButtonData( + style: ButtonStyle( + backgroundColor: backgroundColor != null + ? MaterialStateProperty.all(backgroundColor) + : null, + elevation: elevation != null + ? MaterialStateProperty.all(elevation) + : null, + padding: MaterialStateProperty.all( + const EdgeInsets.symmetric(horizontal: 8), + ), + textStyle: textStyle != null + ? MaterialStateProperty.all(textStyle) + : null, + ), ), ), ), @@ -60,16 +75,18 @@ class _ElevatedButtonChild extends StatelessWidget { required this.icon, required this.iconData, required this.text, + this.childAlignment, }); final String text; final IconData? iconData; final Widget? icon; + final MainAxisAlignment? childAlignment; @override Widget build(final BuildContext context) { return Row( - mainAxisAlignment: MainAxisAlignment.center, + mainAxisAlignment: childAlignment ?? MainAxisAlignment.center, children: [ (icon != null || iconData != null) ? _Icon( @@ -85,75 +102,6 @@ class _ElevatedButtonChild extends StatelessWidget { } } -// /// Default styles are for elevated buttons on canvas background -// class D3pElevatedButtonThemeData { -// final Color backgroundColor; -// final Color foregroundColor; - -// // const D3pElevatedButtonThemeData._({ -// // required this.backgroundColor, -// // required this.foregroundColor, -// // }); - -// D3pElevatedButtonThemeData.active(final ThemeData themeData) -// : backgroundColor = themeData.colorScheme.primary, -// foregroundColor = themeData.colorScheme.onPrimary; - -// D3pElevatedButtonThemeData.disabled(final ThemeData themeData) -// : backgroundColor = themeData.cardColor, -// foregroundColor = themeData.colorScheme.onSurface.withOpacity(0.50); -// } - -// class D3pElevatedButtonStyle { -// final bool isButtonActive; -// final ThemeData themeData; - -// final Size? minimumSize; -// final Color? foregroundColor; -// final Color? backgroundColor; - -// const D3pElevatedButtonStyle({ -// required this.isButtonActive, -// required this.themeData, -// required this.foregroundColor, -// required this.backgroundColor, -// required this.minimumSize, -// }); - -// MaterialElevatedButtonData resolveMaterial({ -// required final Widget? icon, -// required final IconData? iconData, -// required final String text, -// }) { -// return MaterialElevatedButtonData( -// child: _ElevatedButtonChild( -// icon: icon, -// iconData: iconData, -// text: text, -// ), -// ); -// } - -// CupertinoElevatedButtonData resolveCupertino({ -// required final BuildContext context, -// required final Widget? icon, -// required final IconData? iconData, -// required final String text, -// }) { -// return CupertinoElevatedButtonData( -// // color: Colors.orange, -// originalStyle: false, -// // onPressed: () {}, -// // disabledColor: Colors.amber, -// child: _ElevatedButtonChild( -// icon: icon, -// iconData: iconData, -// text: text, -// ), -// ); -// } -// } - class _Icon extends StatelessWidget { const _Icon({ required this.iconData, diff --git a/lib/core/widgets/buttons/enum_button.dart b/lib/core/widgets/buttons/enum_button.dart index bd05e27b..3001bf60 100644 --- a/lib/core/widgets/buttons/enum_button.dart +++ b/lib/core/widgets/buttons/enum_button.dart @@ -12,7 +12,12 @@ class EnumButton extends StatelessWidget { this.onPressed, // this.backgroundColor, this.padding, + this.child, }) : border = const RoundedRectangleBorder(), + assert( + child != null || text != null, + 'Either child or text must be provided', + ), super(key: key); static const buttonRadius = Radius.circular(8); @@ -20,9 +25,10 @@ class EnumButton extends StatelessWidget { final void Function()? onPressed; // final Color? backgroundColor; final RoundedRectangleBorder border; - final String text; + final String? text; final EdgeInsetsGeometry? padding; final bool isChosen; + final Widget? child; @override Widget build(final BuildContext context) { @@ -41,9 +47,17 @@ class EnumButton extends StatelessWidget { _Icon( isEmpty: !isChosen, ), - Text( - text, - // style: theme.textTheme.labelLarge, + Flexible( + child: child != null + ? child! + : Text( + text ?? '', + // style: theme.textTheme.labelLarge, + ), + ), + // placeholder to make flexible centered + const _Icon( + isEmpty: true, ), ], ), diff --git a/lib/core/widgets/input/textformfield/bottom_help_text.dart b/lib/core/widgets/input/textformfield/bottom_help_text.dart index f2902e10..992e104d 100644 --- a/lib/core/widgets/input/textformfield/bottom_help_text.dart +++ b/lib/core/widgets/input/textformfield/bottom_help_text.dart @@ -12,7 +12,7 @@ class _BottomHelpText extends StatelessWidget { padding: const EdgeInsets.only(top: 8, left: 16, right: 16), child: Text( bottomHelpText!, - style: Theme.of(context).customTextStyles.dp3BodySmall, + style: Theme.of(context).customTextStyles.d3pBodySmall, ), ) : const SizedBox(); diff --git a/lib/core/widgets/input/textformfield/textformfield.dart b/lib/core/widgets/input/textformfield/textformfield.dart index d247623f..648ae690 100644 --- a/lib/core/widgets/input/textformfield/textformfield.dart +++ b/lib/core/widgets/input/textformfield/textformfield.dart @@ -5,6 +5,7 @@ import 'package:threedpass/core/theme/d3p_colors.dart'; import 'package:threedpass/core/theme/d3p_special_styles.dart'; import 'package:threedpass/core/theme/d3p_theme.dart'; import 'package:threedpass/core/utils/empty_function.dart'; +import 'package:threedpass/core/widgets/paddings.dart'; part 'suffix_button.dart'; part 'bottom_help_text.dart'; @@ -12,7 +13,6 @@ part 'label.dart'; class D3pTextFormField extends StatelessWidget { D3pTextFormField({ - final Key? key, final TextEditingController? controller, this.hintText, this.labelText, @@ -31,8 +31,13 @@ class D3pTextFormField extends StatelessWidget { this.maxLines, this.isCollapsed = false, this.autofocus = false, - }) : controller = controller ?? TextEditingController(), - super(key: key); + this.makeLabelOutside = false, + this.contentPadding = + const EdgeInsets.symmetric(horizontal: 8, vertical: 12), + this.focusedBorder, + this.border, + super.key, + }) : controller = controller ?? TextEditingController(); final void Function()? onLabelButtonPressed; final void Function()? onSuffixButtonPressed; @@ -55,25 +60,40 @@ class D3pTextFormField extends StatelessWidget { final bool obscureText; final bool isCollapsed; final bool autofocus; + final EdgeInsetsGeometry contentPadding; + final InputBorder? border; + final InputBorder? focusedBorder; + + final bool makeLabelOutside; TextStyle hintStyle(final CustomTextStyles textStyles) { return textStyles.d3pBodyMedium.copyWith(color: D3pColors.disabled); } - UnderlineInputBorder get focusedBorder => UnderlineInputBorder( + int? get mMaxLines => obscureText ? 1 : maxLines ?? 1; + // double? get mHeight => labelText == null ? 44 : null; + InputBorder get defaultFocusedBorder => UnderlineInputBorder( borderSide: BorderSide(color: D3pThemeData.mainColor), ); - int? get mMaxLines => obscureText ? 1 : maxLines ?? 1; - - double? get mHeight => labelText == null ? 44 : null; - @override Widget build(final BuildContext context) { final textStyle = Theme.of(context).customTextStyles; return Column( mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, children: [ + if (makeLabelOutside) + Column( + children: [ + Text( + labelText ?? '', + style: + textStyle.d3pBodySmall.copyWith(color: D3pColors.disabled), + ), + const SizedBoxH4(), + ], + ), SizedBox( // height: 55, child: TextFormField( @@ -81,10 +101,10 @@ class D3pTextFormField extends StatelessWidget { decoration: InputDecoration( isDense: true, filled: true, - focusedBorder: focusedBorder, - contentPadding: - const EdgeInsets.symmetric(horizontal: 8, vertical: 12), - label: _Label(labelText).build(context), + border: border, + focusedBorder: focusedBorder ?? defaultFocusedBorder, + contentPadding: contentPadding, + label: makeLabelOutside ? null : _Label(labelText).build(context), suffixIcon: _SuffixButton( labelButton: labelButton, suffixButton: suffixButton, diff --git a/lib/core/widgets/slider/slider.dart b/lib/core/widgets/slider/slider.dart index 58290d51..8a3a4b16 100644 --- a/lib/core/widgets/slider/slider.dart +++ b/lib/core/widgets/slider/slider.dart @@ -38,13 +38,13 @@ class _State extends State { if (widget.label != null) Text( widget.label!.tr(), - style: textStyles.dp3BodySmall, + style: textStyles.d3pBodySmall, ), Row( children: [ Text( '${widget.minValue}', - style: textStyles.dp3BodySmall, + style: textStyles.d3pBodySmall, ), Flexible( child: Container( @@ -60,7 +60,7 @@ class _State extends State { ), Text( '${widget.maxValue}', - style: textStyles.dp3BodySmall, + style: textStyles.d3pBodySmall, ), ], ), @@ -68,7 +68,7 @@ class _State extends State { padding: const EdgeInsets.only(top: 0, left: 16, right: 16), child: Text( 'pixel_ratio_help_text'.tr(), - style: textStyles.dp3BodySmall, + style: textStyles.d3pBodySmall, ), ), ], diff --git a/lib/features/accounts/presentation/pages/create_account/create_account_mnemonic_confirm.dart b/lib/features/accounts/presentation/pages/create_account/create_account_mnemonic_confirm.dart index 57487af5..3ff387af 100644 --- a/lib/features/accounts/presentation/pages/create_account/create_account_mnemonic_confirm.dart +++ b/lib/features/accounts/presentation/pages/create_account/create_account_mnemonic_confirm.dart @@ -3,6 +3,7 @@ import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:threedpass/core/theme/d3p_special_styles.dart'; +import 'package:threedpass/core/widgets/paddings.dart'; import 'package:threedpass/core/widgets/text/d3p_body_medium_text.dart'; import 'package:threedpass/features/accounts/bloc/account_store_bloc/account_store_bloc.dart'; import 'package:threedpass/features/accounts/bloc/mnemonic_input_cubit.dart'; @@ -29,7 +30,7 @@ class CreateAccountMnemonicConfirmPage extends StatelessWidget { child: SubmitMnemonicConfirmButton(), ), children: [ - const SizedBox(height: 16), + const SizedBoxH16(), Text( 'backup_confirm_header'.tr(), style: Theme.of(context) @@ -37,7 +38,7 @@ class CreateAccountMnemonicConfirmPage extends StatelessWidget { .d3ptitleLarge .copyWith(fontWeight: FontWeight.bold), ), - const SizedBox(height: 16), + const SizedBoxH16(), const D3pBodyMediumText('backup_confirm_text'), const SizedBox(height: 12), const Align( diff --git a/lib/features/accounts/presentation/pages/create_account/create_account_wrapper.dart b/lib/features/accounts/presentation/pages/create_account/create_account_wrapper.dart index 7621fbc6..480447d1 100644 --- a/lib/features/accounts/presentation/pages/create_account/create_account_wrapper.dart +++ b/lib/features/accounts/presentation/pages/create_account/create_account_wrapper.dart @@ -6,7 +6,6 @@ import 'package:threedpass/core/polkawallet/app_service.dart'; import 'package:threedpass/core/polkawallet/bloc/app_service_cubit.dart'; import 'package:threedpass/features/accounts/bloc/account_store_bloc/account_store_bloc.dart'; import 'package:threedpass/features/preview_page/bloc/outer_context_cubit.dart'; -import 'package:threedpass/router/route_paths.dart'; @RoutePage() class CreateAccountPageWrapper extends StatelessWidget diff --git a/lib/features/wallet_screen/bloc/transfer_info_cubit.dart b/lib/features/wallet_screen/bloc/transfer_info_cubit.dart index f5b64938..6c73a1dd 100644 --- a/lib/features/wallet_screen/bloc/transfer_info_cubit.dart +++ b/lib/features/wallet_screen/bloc/transfer_info_cubit.dart @@ -1,8 +1,8 @@ import 'package:copy_with_extension/copy_with_extension.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; -import 'package:fluttertoast/fluttertoast.dart'; import 'package:polkawallet_sdk/api/types/txInfoData.dart'; +import 'package:polkawallet_sdk/storage/types/keyPairData.dart'; import 'package:threedpass/core/polkawallet/app_service.dart'; import 'package:threedpass/core/polkawallet/bloc/app_service_cubit.dart'; import 'package:threedpass/core/polkawallet/utils/transfer_type.dart'; @@ -14,17 +14,29 @@ part 'transfer_info_cubit.g.dart'; class TransferInfoCubit extends Cubit { TransferInfoCubit({ - required final double balance, required this.metaDTO, required this.appService, }) : super( TransferInfo( - balance: balance, + fromAddresses: [initialFrom(appService)], + toAddresses: [], fees: null, type: TransferTypeValue.defaultType, ), ); + static _FromAddressData initialFrom(final AppService appService) { + final account = appService.keyring.current; + final balance = double.tryParse( + appService.chosenAccountBalance.value.availableBalance.toString(), + ); + return _FromAddressData( + amount: 0, + balance: balance, + data: account, + ); + } + final TransferMetaDTO metaDTO; final AppService appService; @@ -106,13 +118,35 @@ class TransferInfoCubit extends Cubit { @CopyWith() class TransferInfo { // Max avaliable balance in wallet in human-readable double format - final double balance; + // final double balance; final TxFeeEstimateResult? fees; final TransferType type; + final List<_FromAddressData> fromAddresses; + final List<_ToAddressData> toAddresses; const TransferInfo({ - required this.balance, + required this.fromAddresses, + required this.toAddresses, required this.fees, required this.type, }); } + +class _FromAddressData { + const _FromAddressData({ + required this.amount, + required this.balance, + required this.data, + }); + + final KeyPairData? data; + final double? amount; + final double? balance; +} + +class _ToAddressData { + const _ToAddressData({ + required this.data, + }); + final KeyPairData? data; +} diff --git a/lib/features/wallet_screen/bloc/transfer_info_cubit.g.dart b/lib/features/wallet_screen/bloc/transfer_info_cubit.g.dart index ae8b1976..7bfd4e9b 100644 --- a/lib/features/wallet_screen/bloc/transfer_info_cubit.g.dart +++ b/lib/features/wallet_screen/bloc/transfer_info_cubit.g.dart @@ -7,7 +7,9 @@ part of 'transfer_info_cubit.dart'; // ************************************************************************** abstract class _$TransferInfoCWProxy { - TransferInfo balance(double balance); + TransferInfo fromAddresses(List<_FromAddressData> fromAddresses); + + TransferInfo toAddresses(List<_ToAddressData> toAddresses); TransferInfo fees(TxFeeEstimateResult? fees); @@ -20,7 +22,8 @@ abstract class _$TransferInfoCWProxy { /// TransferInfo(...).copyWith(id: 12, name: "My name") /// ```` TransferInfo call({ - double? balance, + List<_FromAddressData>? fromAddresses, + List<_ToAddressData>? toAddresses, TxFeeEstimateResult? fees, TransferType? type, }); @@ -33,7 +36,12 @@ class _$TransferInfoCWProxyImpl implements _$TransferInfoCWProxy { final TransferInfo _value; @override - TransferInfo balance(double balance) => this(balance: balance); + TransferInfo fromAddresses(List<_FromAddressData> fromAddresses) => + this(fromAddresses: fromAddresses); + + @override + TransferInfo toAddresses(List<_ToAddressData> toAddresses) => + this(toAddresses: toAddresses); @override TransferInfo fees(TxFeeEstimateResult? fees) => this(fees: fees); @@ -50,15 +58,22 @@ class _$TransferInfoCWProxyImpl implements _$TransferInfoCWProxy { /// TransferInfo(...).copyWith(id: 12, name: "My name") /// ```` TransferInfo call({ - Object? balance = const $CopyWithPlaceholder(), + Object? fromAddresses = const $CopyWithPlaceholder(), + Object? toAddresses = const $CopyWithPlaceholder(), Object? fees = const $CopyWithPlaceholder(), Object? type = const $CopyWithPlaceholder(), }) { return TransferInfo( - balance: balance == const $CopyWithPlaceholder() || balance == null - ? _value.balance - // ignore: cast_nullable_to_non_nullable - : balance as double, + fromAddresses: + fromAddresses == const $CopyWithPlaceholder() || fromAddresses == null + ? _value.fromAddresses + // ignore: cast_nullable_to_non_nullable + : fromAddresses as List<_FromAddressData>, + toAddresses: + toAddresses == const $CopyWithPlaceholder() || toAddresses == null + ? _value.toAddresses + // ignore: cast_nullable_to_non_nullable + : toAddresses as List<_ToAddressData>, fees: fees == const $CopyWithPlaceholder() ? _value.fees // ignore: cast_nullable_to_non_nullable diff --git a/lib/features/wallet_screen/domain/entities/transfer_history_ui.dart b/lib/features/wallet_screen/domain/entities/transfer_history_ui.dart index 94f60bd4..2c5e7538 100644 --- a/lib/features/wallet_screen/domain/entities/transfer_history_ui.dart +++ b/lib/features/wallet_screen/domain/entities/transfer_history_ui.dart @@ -15,7 +15,7 @@ class TransferHistoryUI { final String fromAddress; final String toAddress; - /// This item is about fact that tokens were send FROM THIS account TO ANOTHER + /// Its says assets were send FROM this TO another final TransferDirection direction; final int decimals; diff --git a/lib/features/wallet_screen/presentation/assets_page/widgets/balance_card/basic_balance_card.dart b/lib/features/wallet_screen/presentation/assets_page/widgets/balance_card/basic_balance_card.dart index 1d329ca8..984ee957 100644 --- a/lib/features/wallet_screen/presentation/assets_page/widgets/balance_card/basic_balance_card.dart +++ b/lib/features/wallet_screen/presentation/assets_page/widgets/balance_card/basic_balance_card.dart @@ -49,7 +49,7 @@ class BasicBalanceRow extends StatelessWidget { children: [ TextSpan( text: ' ' + tokenSymbol, - style: textStyles.dp3BodySmall, + style: textStyles.d3pBodySmall, ), ], ), diff --git a/lib/features/wallet_screen/presentation/transfer_page/transfer_page.dart b/lib/features/wallet_screen/presentation/transfer_page/transfer_page.dart index f3ec464e..d3620be2 100644 --- a/lib/features/wallet_screen/presentation/transfer_page/transfer_page.dart +++ b/lib/features/wallet_screen/presentation/transfer_page/transfer_page.dart @@ -5,18 +5,23 @@ import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:threedpass/core/polkawallet/app_service.dart'; import 'package:threedpass/core/polkawallet/bloc/app_service_cubit.dart'; import 'package:threedpass/core/polkawallet/utils/balance_utils.dart'; +import 'package:threedpass/core/theme/d3p_colors.dart'; +import 'package:threedpass/core/theme/d3p_special_styles.dart'; import 'package:threedpass/core/utils/formatters.dart'; import 'package:threedpass/core/utils/validators.dart'; import 'package:threedpass/core/widgets/buttons/elevated_button.dart'; +import 'package:threedpass/core/widgets/buttons/text_button.dart'; import 'package:threedpass/core/widgets/d3p_scaffold.dart'; import 'package:threedpass/core/widgets/input/textformfield/textformfield.dart'; import 'package:threedpass/core/widgets/paddings.dart'; import 'package:threedpass/features/wallet_screen/bloc/transfer_info_cubit.dart'; import 'package:threedpass/features/wallet_screen/domain/entities/transfer_meta_dto.dart'; +import 'package:threedpass/features/wallet_screen/presentation/transfer_page/widgets/basic_transfer_block.dart'; +import 'package:threedpass/features/wallet_screen/presentation/transfer_page/widgets/basic_transfer_textfield.dart'; +import 'package:threedpass/features/wallet_screen/presentation/transfer_page/widgets/from_address_textfield.dart'; import 'package:threedpass/features/wallet_screen/presentation/transfer_page/widgets/transfer_type_dropdown.dart'; part './widgets/make_transfer_button.dart'; -part 'widgets/from_address_textfield.dart'; part 'widgets/to_address_textfield.dart'; part 'widgets/amount_textfield.dart'; part 'widgets/password_textfield.dart'; @@ -46,28 +51,53 @@ class TransferPage extends StatelessWidget { Flexible( child: SingleChildScrollView( child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 16), + padding: const EdgeInsets.symmetric(horizontal: 8), child: Form( key: _formKey, child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - const SizedBoxH16(), - const _FromAddressTextField(), - const SizedBoxH24(), - _ToAddressTextField( - toAddressController: toAddressController, + // const SizedBoxH16(), + SizedBoxH8(), + ListView.builder( + shrinkWrap: true, + physics: const NeverScrollableScrollPhysics(), + itemCount: transferInfo.state.fromAddresses.length, + itemBuilder: (context, index) => BasicTransferBlock( + child: Column( + children: [ + const FromAddressTextField(), + SizedBoxH4(), + _PasswordTextField( + passwordController: passwordController, + ), + SizedBoxH4(), + _AmountTextFieldBuilder( + amountController: amountController, + transferMetaDTO: transferInfo.metaDTO, + balance: transferInfo + .state.fromAddresses[index].balance ?? + 0, + ), + ], + ), + ), ), - const SizedBoxH24(), - _AmountTextFieldBuilder( - amountController: amountController, - transferMetaDTO: transferInfo.metaDTO, + + Align( + alignment: Alignment.center, + child: Icon( + Icons.arrow_downward_outlined, + size: 30, + ), ), - const SizedBoxH24(), - _PasswordTextField( - passwordController: passwordController, + + // const SizedBoxH24(), + _ToAddressTextField( + toAddressController: toAddressController, ), - const SizedBoxH24(), + const SizedBoxH16(), + const TransferTypeDropdown(), // const SizedBox(height: 24), // const FeesText(), @@ -78,12 +108,15 @@ class TransferPage extends StatelessWidget { ), ), ), - _MakeTransferButton( - toAddressController: toAddressController, - amountController: amountController, - passwordController: passwordController, - formKey: _formKey, - appService: appService, + Padding( + padding: const EdgeInsets.only(bottom: 8), + child: _MakeTransferButton( + toAddressController: toAddressController, + amountController: amountController, + passwordController: passwordController, + formKey: _formKey, + appService: appService, + ), ), ], ), diff --git a/lib/features/wallet_screen/presentation/transfer_page/transfer_page_wrapper.dart b/lib/features/wallet_screen/presentation/transfer_page/transfer_page_wrapper.dart index 32a08f5c..99fb0706 100644 --- a/lib/features/wallet_screen/presentation/transfer_page/transfer_page_wrapper.dart +++ b/lib/features/wallet_screen/presentation/transfer_page/transfer_page_wrapper.dart @@ -18,14 +18,12 @@ class TransferPageWrapper extends StatelessWidget implements AutoRouteWrapper { @override Widget wrappedRoute(final BuildContext context) { final appService = BlocProvider.of(context).state; - final balance = metadata.getBalance(); return MultiBlocProvider( providers: [ BlocProvider( // We are not calculating fees now create: (final _) => TransferInfoCubit( - balance: balance, metaDTO: metadata, appService: appService, )..init(), diff --git a/lib/features/wallet_screen/presentation/transfer_page/widgets/amount_textfield.dart b/lib/features/wallet_screen/presentation/transfer_page/widgets/amount_textfield.dart index f184ab67..aa148ada 100644 --- a/lib/features/wallet_screen/presentation/transfer_page/widgets/amount_textfield.dart +++ b/lib/features/wallet_screen/presentation/transfer_page/widgets/amount_textfield.dart @@ -4,22 +4,20 @@ class _AmountTextFieldBuilder extends StatelessWidget { const _AmountTextFieldBuilder({ required this.amountController, required this.transferMetaDTO, + required this.balance, final Key? key, }) : super(key: key); final TextEditingController amountController; final TransferMetaDTO transferMetaDTO; + final double balance; @override Widget build(final BuildContext context) { - return BlocBuilder( - buildWhen: (final previous, final current) => - previous.balance != current.balance, - builder: (final context, final state) => _AmountTextField( - amountController: amountController, - balance: state.balance, - transferMetaDTO: transferMetaDTO, - ), + return _AmountTextField( + amountController: amountController, + balance: balance, + transferMetaDTO: transferMetaDTO, ); } } @@ -47,7 +45,7 @@ class _AmountTextField extends StatelessWidget { @override Widget build(final BuildContext context) { - return D3pTextFormField( + return BasicTransferTextField( labelText: 'amount_label'.tr( args: [ BalanceUtils.doubleFormat(balance), diff --git a/lib/features/wallet_screen/presentation/transfer_page/widgets/basic_transfer_block.dart b/lib/features/wallet_screen/presentation/transfer_page/widgets/basic_transfer_block.dart new file mode 100644 index 00000000..35172fe9 --- /dev/null +++ b/lib/features/wallet_screen/presentation/transfer_page/widgets/basic_transfer_block.dart @@ -0,0 +1,26 @@ +import 'package:flutter/material.dart'; + +class BasicTransferBlock extends StatelessWidget { + const BasicTransferBlock({ + required this.child, + super.key, + }); + + final Widget child; + + @override + Widget build(final BuildContext context) { + return Card( + shape: const RoundedRectangleBorder( + borderRadius: BorderRadius.all(Radius.circular(16)), + ), + child: Padding( + padding: const EdgeInsets.symmetric( + horizontal: 16, + vertical: 16, + ), + child: child, + ), + ); + } +} diff --git a/lib/features/wallet_screen/presentation/transfer_page/widgets/basic_transfer_textfield.dart b/lib/features/wallet_screen/presentation/transfer_page/widgets/basic_transfer_textfield.dart new file mode 100644 index 00000000..bf3ec857 --- /dev/null +++ b/lib/features/wallet_screen/presentation/transfer_page/widgets/basic_transfer_textfield.dart @@ -0,0 +1,45 @@ +import 'package:flutter/material.dart'; +import 'package:threedpass/core/theme/d3p_theme.dart'; +import 'package:threedpass/core/widgets/input/textformfield/textformfield.dart'; + +class BasicTransferTextField extends D3pTextFormField { + BasicTransferTextField({ + super.autofocus, + super.bottomHelpText, + super.controller, + super.enabled, + super.hintText, + super.inputFormatters, + super.isCollapsed, + super.key, + super.keyboardType, + super.labelButton, + super.labelText, + super.maxLen, + super.maxLines, + super.obscureText, + super.onChanged, + super.onLabelButtonPressed, + super.onSuffixButtonPressed, + super.suffixButton, + super.validator, + super.makeLabelOutside = true, + super.border = const UnderlineInputBorder( + borderSide: BorderSide.none, + borderRadius: BorderRadius.all( + Radius.circular(8), + ), + ), + // super.focusedBorder = overrideFocusedBorder, + super.contentPadding = + const EdgeInsets.symmetric(horizontal: 8, vertical: 12), + }) : super( + focusedBorder: OutlineInputBorder( + borderSide: BorderSide(color: D3pThemeData.mainColor), + borderRadius: const BorderRadius.all( + Radius.circular(8), + ), + gapPadding: 4, + ), + ); +} diff --git a/lib/features/wallet_screen/presentation/transfer_page/widgets/from_address_textfield.dart b/lib/features/wallet_screen/presentation/transfer_page/widgets/from_address_textfield.dart index 892d9c27..4352f3c8 100644 --- a/lib/features/wallet_screen/presentation/transfer_page/widgets/from_address_textfield.dart +++ b/lib/features/wallet_screen/presentation/transfer_page/widgets/from_address_textfield.dart @@ -1,19 +1,151 @@ -part of '../transfer_page.dart'; +import 'package:easy_localization/easy_localization.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:flutter_platform_widgets/flutter_platform_widgets.dart'; +import 'package:threedpass/core/polkawallet/bloc/app_service_cubit.dart'; +import 'package:threedpass/core/theme/d3p_colors.dart'; +import 'package:threedpass/core/theme/d3p_special_styles.dart'; +import 'package:threedpass/core/utils/formatters.dart'; +import 'package:threedpass/core/widgets/buttons/elevated_button.dart'; +import 'package:threedpass/core/widgets/buttons/enum_button.dart'; +import 'package:threedpass/core/widgets/paddings.dart'; -class _FromAddressTextField extends StatelessWidget { - const _FromAddressTextField({final Key? key}) : super(key: key); +class FromAddressTextField extends StatelessWidget { + const FromAddressTextField({final Key? key}) : super(key: key); @override Widget build(final BuildContext context) { final appService = BlocProvider.of(context).state; - return D3pTextFormField( - enabled: false, - labelText: 'from_address_label'.tr(), - controller: TextEditingController( - text: Fmt.shorterAddress( - appService.keyring.current.address, + final theme = Theme.of(context); + // Colors from https://github.com/flutter/flutter/blob/936763f58963ef3dd103986fc232310c43360344/packages/flutter/lib/src/material/input_decorator.dart#L4561 + + // switch (Theme.of(context).brightness) { + // case Brightness.dark: + // return const Color(0x0DFFFFFF); + // case Brightness.light: + // return const Color(0x05000000) ; + // } + final textStyle = Theme.of(context).customTextStyles; + + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + 'from_address_label'.tr(), + style: textStyle.d3pBodySmall.copyWith(color: D3pColors.disabled), + ), + const SizedBoxH4(), + SizedBox( + height: 43, + child: D3pElevatedButton( + text: null, + onPressed: () => openDialog(context), + backgroundColor: const Color(0x0DFFFFFF), + elevation: 0, + childAlignment: MainAxisAlignment.start, + textStyle: textStyle.d3pBodyMedium, + child: const Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text('Account name'), + Icon(Icons.keyboard_arrow_down_rounded), + ], + ), + ), + ), + ], + ); + + // return BasicTransferTextField( + // enabled: false, + // labelText: 'from_address_label'.tr(), + // controller: TextEditingController( + // text: Fmt.shorterAddress( + // appService.keyring.current.address, + // ), + // ), + // ); + } + + Future openDialog(final BuildContext context) { + final accounts = BlocProvider.of(context) + .state + .keyring + .allAccounts; + + //BlocProvider.of(context).state.plugin.sdk.api.account.queryBalance + + // Fmt.shorterAddress( + // appService.keyring.current.address, + // ), + return showPlatformModalSheet( + context: context, + material: MaterialModalSheetData( + shape: const RoundedRectangleBorder( + side: BorderSide.none, + borderRadius: BorderRadius.only( + topLeft: Radius.circular(16), + topRight: Radius.circular(16), + ), ), ), + builder: (final _) => Column( + children: [ + const SizedBoxH24(), + ListView.builder( + shrinkWrap: true, + itemCount: accounts.length, + itemBuilder: (final context, final index) => EnumButton( + text: null, + isChosen: false, + onPressed: () {}, + child: _AccountChooseTileText( + address: accounts[index].address, + name: accounts[index].name, + ), + ), + ), + ], + ), + ); + } +} + +class _AccountChooseTileText extends StatelessWidget { + const _AccountChooseTileText({ + required this.address, + required this.name, + }); + + final String? name; + final String? address; + + String fixedName() { + if (name != null) { + return name! + ' '; + } else { + return ''; + } + } + + String shortAddress() { + return Fmt.shorterAddress(address); + } + + @override + Widget build(final BuildContext context) { + final textStyles = Theme.of(context).customTextStyles; + return Text.rich( + TextSpan( + text: fixedName(), + children: [ + TextSpan( + text: shortAddress(), + style: textStyles.d3pBodyMedium.copyWith(color: D3pColors.disabled), + ), + ], + ), ); + // return '${fixedName()}${shortAddress()}'; } } diff --git a/lib/features/wallet_screen/presentation/transfer_page/widgets/password_textfield.dart b/lib/features/wallet_screen/presentation/transfer_page/widgets/password_textfield.dart index 3bc3a6fa..f577b296 100644 --- a/lib/features/wallet_screen/presentation/transfer_page/widgets/password_textfield.dart +++ b/lib/features/wallet_screen/presentation/transfer_page/widgets/password_textfield.dart @@ -16,14 +16,13 @@ class _PasswordTextField extends StatelessWidget { @override Widget build(final BuildContext context) { - return D3pTextFormField( + return BasicTransferTextField( labelText: 'enter_password_label'.tr(), controller: passwordController, hintText: 'enter_password_hint'.tr(), validator: _passValidator, obscureText: true, maxLines: 1, - // hintText: 'amount_hint'.tr(), ); } } diff --git a/lib/features/wallet_screen/presentation/transfer_page/widgets/to_address_textfield.dart b/lib/features/wallet_screen/presentation/transfer_page/widgets/to_address_textfield.dart index 9cd34553..8ee340ea 100644 --- a/lib/features/wallet_screen/presentation/transfer_page/widgets/to_address_textfield.dart +++ b/lib/features/wallet_screen/presentation/transfer_page/widgets/to_address_textfield.dart @@ -10,11 +10,22 @@ class _ToAddressTextField extends StatelessWidget { @override Widget build(final BuildContext context) { - return D3pTextFormField( - labelText: 'to_address_label'.tr(), - controller: toAddressController, - maxLines: 1, - hintText: 'to_address_hint'.tr(), + return Card( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.all(Radius.circular(16)), + ), + child: Padding( + padding: EdgeInsets.symmetric( + horizontal: 16, + vertical: 16, + ), + child: BasicTransferTextField( + labelText: 'to_address_label'.tr(), + controller: toAddressController, + maxLines: 1, + hintText: 'to_address_hint'.tr(), + ), + ), ); } } diff --git a/lib/features/wallet_screen/presentation/transfer_page/widgets/transfer_type_dropdown.dart b/lib/features/wallet_screen/presentation/transfer_page/widgets/transfer_type_dropdown.dart index 58b0e9ca..9614b1a3 100644 --- a/lib/features/wallet_screen/presentation/transfer_page/widgets/transfer_type_dropdown.dart +++ b/lib/features/wallet_screen/presentation/transfer_page/widgets/transfer_type_dropdown.dart @@ -21,14 +21,17 @@ class TransferTypeDropdown extends StatelessWidget { final initialValue = BlocProvider.of(context).state.type == TransferType.transferKeepAlive; - return D3pSwitchButton( - initialValue: initialValue, - helpText: 'transfer_keep_alive_help'.tr(), - onChanged: (final value) => onChanged( - context, - value ? TransferType.transferKeepAlive : TransferType.transfer, + return Padding( + padding: const EdgeInsets.symmetric(horizontal: 8), + child: D3pSwitchButton( + initialValue: initialValue, + helpText: 'transfer_keep_alive_help'.tr(), + onChanged: (final value) => onChanged( + context, + value ? TransferType.transferKeepAlive : TransferType.transfer, + ), + text: 'choose_transfer_keep_alive'.tr(), ), - text: 'choose_transfer_keep_alive'.tr(), ); } } diff --git a/lib/features/wallet_screen/presentation/widgets/asset_balance_text.dart b/lib/features/wallet_screen/presentation/widgets/asset_balance_text.dart index fec1ea92..ba3cf007 100644 --- a/lib/features/wallet_screen/presentation/widgets/asset_balance_text.dart +++ b/lib/features/wallet_screen/presentation/widgets/asset_balance_text.dart @@ -20,7 +20,7 @@ class AssetBalanceText extends StatelessWidget { children: [ TextSpan( text: ' ' + tokenSymbol, - style: styles.dp3BodySmall, + style: styles.d3pBodySmall, ), ], ), From 7b672e1d8a9a78e888900936ee126727f09f0306 Mon Sep 17 00:00:00 2001 From: L3odr0id Date: Fri, 29 Sep 2023 19:49:09 +0300 Subject: [PATCH 2/7] WIP: Assets page panel --- assets/translations/en.json | 2 +- lib/core/theme/d3p_special_styles.dart | 5 +++ lib/core/widgets/buttons/icon_button.dart | 32 ++++++++++++------- .../presentation/assets_page/assets_page.dart | 2 +- .../widgets/asset_page_appbar.dart | 23 +++++++------ .../assets_page/widgets/buttons_panel.dart | 12 ++----- .../widgets/coin_transfer_button.dart | 12 +++++-- .../non_native_tokens/assets_column.dart | 2 +- .../assets_page/widgets/recieve_button.dart | 12 +++++-- .../recieve_page/widgets/qr_code.dart | 5 +-- 10 files changed, 66 insertions(+), 41 deletions(-) diff --git a/assets/translations/en.json b/assets/translations/en.json index b79a338e..b81d38e6 100644 --- a/assets/translations/en.json +++ b/assets/translations/en.json @@ -223,7 +223,7 @@ "balance_avaliable_title": "Available", "balance_locked_title": "Locked", "balance_reserved_title": "Reserved", - "transfer_coins_button_label": "Transfer", + "transfer_coins_button_label": "Send", "recieve_coins_button_label": "Recieve", "remove_account_button_label": "Delete account", diff --git a/lib/core/theme/d3p_special_styles.dart b/lib/core/theme/d3p_special_styles.dart index b13be9b4..d7d88262 100644 --- a/lib/core/theme/d3p_special_styles.dart +++ b/lib/core/theme/d3p_special_styles.dart @@ -95,3 +95,8 @@ extension SpecialText on CustomTextStyles { TextStyle get d3pSettingsHeaderSmall => themeData.textTheme.bodySmall! .copyWith(color: themeData.customColors.moreFadedGrey); } + +extension Buttons on CustomTextStyles { + TextStyle get d3pFloatingButton => themeData.textTheme.bodyMedium! + .copyWith(letterSpacing: 1.2, fontWeight: FontWeight.w500); +} diff --git a/lib/core/widgets/buttons/icon_button.dart b/lib/core/widgets/buttons/icon_button.dart index 50a5757b..84ecb5fe 100644 --- a/lib/core/widgets/buttons/icon_button.dart +++ b/lib/core/widgets/buttons/icon_button.dart @@ -10,12 +10,14 @@ class D3pIconButton extends StatelessWidget { this.splashRadius, this.emptyContraints = false, super.key, + this.text, }); const D3pIconButton.fake({ super.key, }) : iconData = Icons.abc, size = null, + text = null, iconColor = Colors.transparent, emptyContraints = false, splashRadius = null, @@ -27,21 +29,27 @@ class D3pIconButton extends StatelessWidget { final double? size; final bool emptyContraints; final double? splashRadius; + final String? text; @override Widget build(final BuildContext context) { - return PlatformIconButton( - icon: Icon( - iconData, - size: size, - color: iconColor, - ), - onPressed: onPressed, - material: (final _, final __) => MaterialIconButtonData( - padding: EdgeInsets.zero, - constraints: emptyContraints ? const BoxConstraints() : null, - splashRadius: splashRadius, - ), + return Column( + children: [ + PlatformIconButton( + icon: Icon( + iconData, + size: size, + color: iconColor, + ), + onPressed: onPressed, + material: (final _, final __) => MaterialIconButtonData( + padding: EdgeInsets.zero, + constraints: emptyContraints ? const BoxConstraints() : null, + splashRadius: splashRadius, + ), + ), + if (text != null) Text(text!), + ], ); } } diff --git a/lib/features/wallet_screen/presentation/assets_page/assets_page.dart b/lib/features/wallet_screen/presentation/assets_page/assets_page.dart index 8b10e48c..5fe83f55 100644 --- a/lib/features/wallet_screen/presentation/assets_page/assets_page.dart +++ b/lib/features/wallet_screen/presentation/assets_page/assets_page.dart @@ -37,7 +37,7 @@ class AssetsPage extends StatelessWidget { // SizedBoxH24(), SizedBoxH8(), CoinsBalance(), - SizedBoxH16(), + SizedBoxH8(), AssetPageButtonsPanel(), Flexible( child: NonNativeTokens(), diff --git a/lib/features/wallet_screen/presentation/assets_page/widgets/asset_page_appbar.dart b/lib/features/wallet_screen/presentation/assets_page/widgets/asset_page_appbar.dart index b29cf07f..9093f6e3 100644 --- a/lib/features/wallet_screen/presentation/assets_page/widgets/asset_page_appbar.dart +++ b/lib/features/wallet_screen/presentation/assets_page/widgets/asset_page_appbar.dart @@ -38,6 +38,7 @@ class AssetPageAppbar extends AppBar { const SizedBox(width: 16), Column( mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, children: [ Text( Fmt.shorterAddress(account.address), @@ -51,16 +52,20 @@ class AssetPageAppbar extends AppBar { ], ), const SizedBox(width: 16), - SizedBox( + Container( + color: Colors.red, width: D3pAddressIcon.defaultSize, - child: D3pIconButton( - emptyContraints: true, - iconData: Icons.copy, - size: 20, - iconColor: themeData.customColors.appBarButton, - onPressed: () => copyAndNotify( - textToCopy: account.address!, - textToShow: 'address_copied_to_clipboard'.tr(), + child: Align( + alignment: Alignment.center, + child: D3pIconButton( + emptyContraints: true, + iconData: Icons.copy, + size: 20, + iconColor: themeData.customColors.appBarButton, + onPressed: () => copyAndNotify( + textToCopy: account.address!, + textToShow: 'address_copied_to_clipboard'.tr(), + ), ), ), ), diff --git a/lib/features/wallet_screen/presentation/assets_page/widgets/buttons_panel.dart b/lib/features/wallet_screen/presentation/assets_page/widgets/buttons_panel.dart index 1752e01d..3693899f 100644 --- a/lib/features/wallet_screen/presentation/assets_page/widgets/buttons_panel.dart +++ b/lib/features/wallet_screen/presentation/assets_page/widgets/buttons_panel.dart @@ -8,17 +8,11 @@ class AssetPageButtonsPanel extends StatelessWidget { @override Widget build(final BuildContext context) { return const Row( - mainAxisAlignment: MainAxisAlignment.spaceAround, + mainAxisAlignment: MainAxisAlignment.center, children: [ + CoinTransferButton(), SizedBox(width: 16), - Flexible( - child: CoinTransferButton(), - ), - SizedBox(width: 8), - Flexible( - child: RecieveButton(), - ), - SizedBox(width: 16), + RecieveButton(), ], ); } diff --git a/lib/features/wallet_screen/presentation/assets_page/widgets/coin_transfer_button.dart b/lib/features/wallet_screen/presentation/assets_page/widgets/coin_transfer_button.dart index 34fe91d4..52ff73e9 100644 --- a/lib/features/wallet_screen/presentation/assets_page/widgets/coin_transfer_button.dart +++ b/lib/features/wallet_screen/presentation/assets_page/widgets/coin_transfer_button.dart @@ -3,7 +3,7 @@ import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:threedpass/core/polkawallet/bloc/app_service_cubit.dart'; -import 'package:threedpass/core/widgets/buttons/elevated_button.dart'; +import 'package:threedpass/core/theme/d3p_special_styles.dart'; import 'package:threedpass/features/wallet_screen/domain/entities/transfer_meta_dto.dart'; import 'package:threedpass/features/wallet_screen/presentation/widgets/is_account_ready_builder.dart'; import 'package:threedpass/router/router.gr.dart'; @@ -26,10 +26,16 @@ class CoinTransferButton extends StatelessWidget { @override Widget build(final BuildContext context) { + final style = Theme.of(context).customTextStyles.d3pFloatingButton; + return IsAccountReadyBuilder( builder: (final BuildContext context, final bool isReady) { - return D3pElevatedButton( - text: 'transfer_coins_button_label'.tr(), + return FloatingActionButton.extended( + icon: const Icon(Icons.arrow_upward_rounded), + label: Text( + 'transfer_coins_button_label'.tr(), + style: style, + ), onPressed: isReady ? () => onPressed(context) : null, ); }, diff --git a/lib/features/wallet_screen/presentation/assets_page/widgets/non_native_tokens/assets_column.dart b/lib/features/wallet_screen/presentation/assets_page/widgets/non_native_tokens/assets_column.dart index 1b6b768d..0ee1c35c 100644 --- a/lib/features/wallet_screen/presentation/assets_page/widgets/non_native_tokens/assets_column.dart +++ b/lib/features/wallet_screen/presentation/assets_page/widgets/non_native_tokens/assets_column.dart @@ -17,7 +17,7 @@ class _AssetsColumn extends StatelessWidget { child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - const SizedBoxH24(), + const SizedBoxH16(), const D3pTitleLargeText('assets_title'), Flexible( child: ListView.builder( diff --git a/lib/features/wallet_screen/presentation/assets_page/widgets/recieve_button.dart b/lib/features/wallet_screen/presentation/assets_page/widgets/recieve_button.dart index 413f657e..a93e5036 100644 --- a/lib/features/wallet_screen/presentation/assets_page/widgets/recieve_button.dart +++ b/lib/features/wallet_screen/presentation/assets_page/widgets/recieve_button.dart @@ -1,7 +1,7 @@ import 'package:auto_route/auto_route.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; -import 'package:threedpass/core/widgets/buttons/elevated_button.dart'; +import 'package:threedpass/core/theme/d3p_special_styles.dart'; import 'package:threedpass/router/router.gr.dart'; class RecieveButton extends StatelessWidget { @@ -13,8 +13,14 @@ class RecieveButton extends StatelessWidget { @override Widget build(final BuildContext context) { - return D3pElevatedButton( - text: 'recieve_coins_button_label'.tr(), + final style = Theme.of(context).customTextStyles.d3pFloatingButton; + + return FloatingActionButton.extended( + icon: const Icon(Icons.arrow_downward_rounded), + label: Text( + 'recieve_coins_button_label'.tr(), + style: style, + ), onPressed: () => onPressed(context), ); } diff --git a/lib/features/wallet_screen/presentation/recieve_page/widgets/qr_code.dart b/lib/features/wallet_screen/presentation/recieve_page/widgets/qr_code.dart index 25578424..29cb400a 100644 --- a/lib/features/wallet_screen/presentation/recieve_page/widgets/qr_code.dart +++ b/lib/features/wallet_screen/presentation/recieve_page/widgets/qr_code.dart @@ -7,14 +7,15 @@ class _QRCode extends StatelessWidget { @override Widget build(final BuildContext context) { + final size = MediaQuery.of(context).size.width - 16 * 6; return Container( - height: MediaQuery.of(context).size.width - 16 * 2, + height: size, alignment: Alignment.center, child: QrImageView( padding: EdgeInsets.zero, data: address, version: QrVersions.auto, - size: MediaQuery.of(context).size.width - 16 * 2, + size: size, foregroundColor: Theme.of(context).customColors.themeOpposite, ), ); From c480c058a67788a2e2c0d3ce72a4a33ac14ba5ef Mon Sep 17 00:00:00 2001 From: L3odr0id Date: Fri, 6 Oct 2023 20:13:10 +0300 Subject: [PATCH 3/7] WIP: Multitransfer UI --- assets/translations/en.json | 14 +- lib/core/polkawallet/app_service.dart | 7 - lib/core/polkawallet/utils/transfer_type.dart | 7 +- lib/core/polkawallet/utils/tx_info.dart | 31 +-- lib/core/theme/d3p_special_colors.dart | 5 + lib/core/theme/d3p_special_styles.dart | 11 +- lib/core/widgets/buttons/elevated_button.dart | 10 +- .../buttons/floating_action_button.dart | 50 +++++ .../input/textformfield/textformfield.dart | 3 +- .../bloc/transfer_info_cubit.dart | 202 +++++++++++++----- .../bloc/transfer_info_cubit.g.dart | 202 ++++++++++++++++-- .../domain/entities/transfer.dart | 15 +- .../domain/entities/transfer_meta_dto.dart | 194 +++++++++-------- .../presentation/assets_page/assets_page.dart | 1 - .../widgets/asset_page_appbar.dart | 124 +++++++---- .../assets_page/widgets/buttons_panel.dart | 3 +- .../widgets/coin_transfer_button.dart | 18 +- .../assets_page/widgets/recieve_button.dart | 15 +- .../widgets/asset_transfer_button.dart | 22 +- .../transfer_page/transfer_page.dart | 135 +++++------- .../transfer_page/widgets/add_card_basic.dart | 59 +++++ .../widgets/add_from_card_row.dart | 24 +++ .../widgets/add_to_card_row.dart | 22 ++ .../widgets/amount_textfield.dart | 24 ++- .../widgets/from_address_textfield.dart | 93 ++++++-- .../widgets/from_card_basic.dart | 29 +++ .../widgets/from_card_many_to_one.dart | 39 ++++ .../widgets/from_card_one_to_many.dart | 22 ++ .../widgets/froms_list_view.dart | 36 ++++ .../widgets/make_transfer_button.dart | 1 - .../widgets/password_textfield.dart | 9 +- .../widgets/to_address_textfield.dart | 29 +-- .../transfer_page/widgets/to_card_basic.dart | 19 ++ .../widgets/to_card_many_to_one.dart | 22 ++ .../widgets/to_card_one_to_many.dart | 39 ++++ .../transfer_page/widgets/tos_list_view.dart | 36 ++++ ...ropdown.dart => transfer_type_switch.dart} | 12 +- packages/super_core/lib/list_extentions.dart | 14 ++ packages/super_core/lib/super_core.dart | 1 + pubspec.lock | 4 +- pubspec.yaml | 2 +- 41 files changed, 1211 insertions(+), 394 deletions(-) create mode 100644 lib/core/widgets/buttons/floating_action_button.dart create mode 100644 lib/features/wallet_screen/presentation/transfer_page/widgets/add_card_basic.dart create mode 100644 lib/features/wallet_screen/presentation/transfer_page/widgets/add_from_card_row.dart create mode 100644 lib/features/wallet_screen/presentation/transfer_page/widgets/add_to_card_row.dart create mode 100644 lib/features/wallet_screen/presentation/transfer_page/widgets/from_card_basic.dart create mode 100644 lib/features/wallet_screen/presentation/transfer_page/widgets/from_card_many_to_one.dart create mode 100644 lib/features/wallet_screen/presentation/transfer_page/widgets/from_card_one_to_many.dart create mode 100644 lib/features/wallet_screen/presentation/transfer_page/widgets/froms_list_view.dart create mode 100644 lib/features/wallet_screen/presentation/transfer_page/widgets/to_card_basic.dart create mode 100644 lib/features/wallet_screen/presentation/transfer_page/widgets/to_card_many_to_one.dart create mode 100644 lib/features/wallet_screen/presentation/transfer_page/widgets/to_card_one_to_many.dart create mode 100644 lib/features/wallet_screen/presentation/transfer_page/widgets/tos_list_view.dart rename lib/features/wallet_screen/presentation/transfer_page/widgets/{transfer_type_dropdown.dart => transfer_type_switch.dart} (76%) create mode 100644 packages/super_core/lib/list_extentions.dart diff --git a/assets/translations/en.json b/assets/translations/en.json index b81d38e6..f9184c25 100644 --- a/assets/translations/en.json +++ b/assets/translations/en.json @@ -223,7 +223,7 @@ "balance_avaliable_title": "Available", "balance_locked_title": "Locked", "balance_reserved_title": "Reserved", - "transfer_coins_button_label": "Send", + "transfer_coins_button_label": "Transfer", "recieve_coins_button_label": "Recieve", "remove_account_button_label": "Delete account", @@ -257,8 +257,8 @@ "to_address_hint": "Enter address", "amount_label": "Amount (Balance: {})", "amount_hint": "Enter amount", - "enter_password_hint": "Password", - "enter_password_label": "Your password", + "enter_password_hint": "Enter password", + "enter_password_label": "Password", "existential_deposit_label": "existential deposit", "existential_deposit_text": "The minimum amount thath an account should have to be deemed active.", "estimated_transfer_fee": "Estimated transfer fee", @@ -303,5 +303,11 @@ "status_success": "Success", "status_failed": "Failed", "status_error": "Error", - "error_wrong_amount_int": "A positive integer expected" + "error_wrong_amount_int": "A positive integer expected", + + "@2.9.0":{ + }, + "from_select_account_title": "Select account", + "add_account_from_label": "Add accout to send FROM", + "add_account_to_label": "Add accout to send TO" } \ No newline at end of file diff --git a/lib/core/polkawallet/app_service.dart b/lib/core/polkawallet/app_service.dart index 75d19c7a..2f7e33d0 100644 --- a/lib/core/polkawallet/app_service.dart +++ b/lib/core/polkawallet/app_service.dart @@ -5,7 +5,6 @@ import 'package:flutter/material.dart'; import 'package:logger/logger.dart'; import 'package:polkawallet_sdk/api/types/balanceData.dart'; import 'package:polkawallet_sdk/api/types/networkStateData.dart'; -import 'package:polkawallet_sdk/api/types/txInfoData.dart'; import 'package:polkawallet_sdk/plugin/index.dart'; import 'package:polkawallet_sdk/storage/keyring.dart'; import 'package:threedpass/core/polkawallet/non_native_tokens_api.dart'; @@ -76,12 +75,6 @@ class AppService { ); } } - - TxSenderData get userSenderData => TxSenderData( - keyring.current.address, - keyring.current.pubKey, - ); - // final subScan = SubScanApi(); } diff --git a/lib/core/polkawallet/utils/transfer_type.dart b/lib/core/polkawallet/utils/transfer_type.dart index 58cf8acc..b8723478 100644 --- a/lib/core/polkawallet/utils/transfer_type.dart +++ b/lib/core/polkawallet/utils/transfer_type.dart @@ -1,9 +1,10 @@ class TransferTypeValue { - static const TransferType defaultType = TransferType.transferKeepAlive; + static const TransactionOption defaultType = + TransactionOption.transferKeepAlive; const TransferTypeValue(this.type); - final TransferType type; + final TransactionOption type; @override String toString() { @@ -11,7 +12,7 @@ class TransferTypeValue { } } -enum TransferType { +enum TransactionOption { transfer, transferKeepAlive, } diff --git a/lib/core/polkawallet/utils/tx_info.dart b/lib/core/polkawallet/utils/tx_info.dart index 6fa6f1f4..8b5cc084 100644 --- a/lib/core/polkawallet/utils/tx_info.dart +++ b/lib/core/polkawallet/utils/tx_info.dart @@ -1,21 +1,22 @@ import 'package:logger/logger.dart'; import 'package:polkawallet_sdk/api/types/txInfoData.dart'; import 'package:polkawallet_sdk/plugin/store/balances.dart'; -import 'package:threedpass/core/polkawallet/app_service.dart'; +import 'package:polkawallet_sdk/storage/types/keyPairData.dart'; import 'package:threedpass/core/polkawallet/utils/balance_utils.dart'; -import 'package:threedpass/core/polkawallet/utils/network_state_data_extension.dart'; import 'package:threedpass/core/polkawallet/utils/transfer_type.dart'; import 'package:threedpass/setup.dart'; abstract class TransferTxInfoI { - final AppService appService; + final KeyPairData senderData; + final int decimals; const TransferTxInfoI({ - required this.appService, + required this.decimals, + required this.senderData, }); TxInfoData txInfo( - final TransferType transferType, + final TransactionOption transferType, ); List params(final String? amount, final String toAddress); } @@ -23,18 +24,19 @@ abstract class TransferTxInfoI { class AssetsTransferTx extends TransferTxInfoI { final TokenBalanceData tokenBalanceData; const AssetsTransferTx({ - required super.appService, + required super.decimals, + required super.senderData, required this.tokenBalanceData, }); @override TxInfoData txInfo( - final TransferType transferType, + final TransactionOption transferType, ) => TxInfoData( 'assets', TransferTypeValue(transferType).toString(), - appService.userSenderData, + TxSenderData(senderData.address, senderData.pubKey), ); @override @@ -52,7 +54,7 @@ class AssetsTransferTx extends TransferTxInfoI { final realAmount = BalanceUtils.tokenInt( amount, - tokenBalanceData.decimals ?? appService.networkStateData.safeDecimals, + tokenBalanceData.decimals ?? decimals, ); if (tokenBalanceData.id == null) { @@ -71,19 +73,20 @@ class AssetsTransferTx extends TransferTxInfoI { class CoinsTransferTx extends TransferTxInfoI { const CoinsTransferTx({ - required super.appService, + required super.decimals, + required super.senderData, }); @override TxInfoData txInfo( - final TransferType transferType, + final TransactionOption transferType, ) => TxInfoData( 'balances', TransferTypeValue(transferType).toString(), TxSenderData( - appService.keyring.current.address, - appService.keyring.current.pubKey, + senderData.address, + senderData.pubKey, ), ); @@ -94,7 +97,7 @@ class CoinsTransferTx extends TransferTxInfoI { ) { final realAmount = BalanceUtils.tokenInt( amount, - appService.networkStateData.safeDecimals, + decimals, ); return [ diff --git a/lib/core/theme/d3p_special_colors.dart b/lib/core/theme/d3p_special_colors.dart index 708648d2..a72858f4 100644 --- a/lib/core/theme/d3p_special_colors.dart +++ b/lib/core/theme/d3p_special_colors.dart @@ -61,6 +61,11 @@ extension ScaffoldCustomColors on CustomColors { Color get cardBackground => brightness == Brightness.light ? D3pColors.lightCardBackground : D3pColors.darkCardBackground; + + // https://github.com/flutter/flutter/blob/ad200896cbe17f8b2ae3560f541c1abafa8f4cd1/packages/flutter/lib/src/material/input_decorator.dart#L4564C22-L4564C22 + Color get defaultInputColor => brightness == Brightness.light + ? const Color(0x0A000000) + : const Color(0x1AFFFFFF); } extension PinCodeColors on CustomColors { diff --git a/lib/core/theme/d3p_special_styles.dart b/lib/core/theme/d3p_special_styles.dart index d7d88262..188f2282 100644 --- a/lib/core/theme/d3p_special_styles.dart +++ b/lib/core/theme/d3p_special_styles.dart @@ -1,4 +1,5 @@ import 'package:flutter/material.dart'; +import 'package:threedpass/core/theme/d3p_colors.dart'; import 'package:threedpass/core/theme/d3p_special_colors.dart'; import 'package:threedpass/core/theme/d3p_theme.dart'; @@ -97,6 +98,12 @@ extension SpecialText on CustomTextStyles { } extension Buttons on CustomTextStyles { - TextStyle get d3pFloatingButton => themeData.textTheme.bodyMedium! - .copyWith(letterSpacing: 1.2, fontWeight: FontWeight.w500); + TextStyle get d3pFloatingButton => + themeData.customTextStyles.d3pBodyMedium.copyWith( + fontSize: 16, + letterSpacing: 1.2, + fontWeight: FontWeight.w500, + ); + + TextStyle get hintStyle => d3pBodySmall.copyWith(color: D3pColors.disabled); } diff --git a/lib/core/widgets/buttons/elevated_button.dart b/lib/core/widgets/buttons/elevated_button.dart index ee1f4508..9a40b0e7 100644 --- a/lib/core/widgets/buttons/elevated_button.dart +++ b/lib/core/widgets/buttons/elevated_button.dart @@ -1,5 +1,6 @@ import 'package:flutter/material.dart'; import 'package:flutter_platform_widgets/flutter_platform_widgets.dart'; +import 'package:threedpass/core/theme/d3p_special_styles.dart'; class D3pElevatedButton extends StatelessWidget { const D3pElevatedButton({ @@ -33,6 +34,7 @@ class D3pElevatedButton extends StatelessWidget { @override Widget build(final BuildContext context) { + final style = Theme.of(context).customTextStyles.d3pFloatingButton; return Padding( padding: padding ?? EdgeInsets.zero, child: SizedBox( @@ -60,8 +62,12 @@ class D3pElevatedButton extends StatelessWidget { const EdgeInsets.symmetric(horizontal: 8), ), textStyle: textStyle != null - ? MaterialStateProperty.all(textStyle) - : null, + ? MaterialStateProperty.all( + textStyle, + ) + : MaterialStateProperty.all( + style, + ), ), ), ), diff --git a/lib/core/widgets/buttons/floating_action_button.dart b/lib/core/widgets/buttons/floating_action_button.dart new file mode 100644 index 00000000..e7c39b05 --- /dev/null +++ b/lib/core/widgets/buttons/floating_action_button.dart @@ -0,0 +1,50 @@ +import 'package:easy_localization/easy_localization.dart'; +import 'package:flutter/material.dart'; +import 'package:threedpass/core/theme/d3p_elevated_button_theme.dart'; +import 'package:threedpass/core/theme/d3p_special_styles.dart'; + +class D3pFloatingActionButton extends StatelessWidget { + const D3pFloatingActionButton({ + required this.onPressed, + required this.icons, + required this.text, + required this.heroTag, + super.key, + }); + + final void Function()? onPressed; + final IconData icons; + final String text; + final String heroTag; + + Set calcSets() { + final disableSets = {MaterialState.disabled}; + return onPressed != null ? {} : disableSets; + } + + @override + Widget build(final BuildContext context) { + final theme = Theme.of(context); + final style = theme.customTextStyles.d3pFloatingButton; + final buttonTheme = D3pElevatedButtonTheme.theme(theme); + + final bgColor = buttonTheme.style!.backgroundColor!.resolve(calcSets()); + final fgColor = buttonTheme.style!.foregroundColor!.resolve(calcSets()); + return FloatingActionButton.extended( + heroTag: heroTag, + backgroundColor: bgColor, + foregroundColor: fgColor, + elevation: 2, + disabledElevation: 0, + shape: const RoundedRectangleBorder( + borderRadius: BorderRadius.all(Radius.circular(4.0)), + ), + icon: Icon(icons), + label: Text( + text.tr(), + style: style.copyWith(color: fgColor), + ), + onPressed: onPressed, + ); + } +} diff --git a/lib/core/widgets/input/textformfield/textformfield.dart b/lib/core/widgets/input/textformfield/textformfield.dart index 648ae690..093597cd 100644 --- a/lib/core/widgets/input/textformfield/textformfield.dart +++ b/lib/core/widgets/input/textformfield/textformfield.dart @@ -88,8 +88,7 @@ class D3pTextFormField extends StatelessWidget { children: [ Text( labelText ?? '', - style: - textStyle.d3pBodySmall.copyWith(color: D3pColors.disabled), + style: textStyle.hintStyle, ), const SizedBoxH4(), ], diff --git a/lib/features/wallet_screen/bloc/transfer_info_cubit.dart b/lib/features/wallet_screen/bloc/transfer_info_cubit.dart index 6c73a1dd..60d4733b 100644 --- a/lib/features/wallet_screen/bloc/transfer_info_cubit.dart +++ b/lib/features/wallet_screen/bloc/transfer_info_cubit.dart @@ -3,11 +3,9 @@ import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:polkawallet_sdk/api/types/txInfoData.dart'; import 'package:polkawallet_sdk/storage/types/keyPairData.dart'; +import 'package:super_core/super_core.dart'; import 'package:threedpass/core/polkawallet/app_service.dart'; -import 'package:threedpass/core/polkawallet/bloc/app_service_cubit.dart'; import 'package:threedpass/core/polkawallet/utils/transfer_type.dart'; -import 'package:threedpass/features/wallet_screen/bloc/notifications_cubit.dart'; -import 'package:threedpass/features/wallet_screen/domain/entities/transfer.dart'; import 'package:threedpass/features/wallet_screen/domain/entities/transfer_meta_dto.dart'; part 'transfer_info_cubit.g.dart'; @@ -19,21 +17,30 @@ class TransferInfoCubit extends Cubit { }) : super( TransferInfo( fromAddresses: [initialFrom(appService)], - toAddresses: [], + toAddresses: [ + ToAddressData( + toAddressController: TextEditingController(), + ), + ], fees: null, type: TransferTypeValue.defaultType, + amounts: [ + SendAmountData( + amountController: TextEditingController(), + ), + ], ), ); - static _FromAddressData initialFrom(final AppService appService) { + static FromAddressData initialFrom(final AppService appService) { final account = appService.keyring.current; - final balance = double.tryParse( - appService.chosenAccountBalance.value.availableBalance.toString(), - ); - return _FromAddressData( - amount: 0, - balance: balance, + // final balance = double.tryParse( + // appService.chosenAccountBalance.value.availableBalance.toString(), + // ); + return FromAddressData( data: account, + // addressController: TextEditingController(), + passwordController: TextEditingController(), ); } @@ -83,70 +90,167 @@ class TransferInfoCubit extends Cubit { required final String password, required final GlobalKey formKey, }) async { - final txInfo = metaDTO.getTxInfo(state.type); - final params = metaDTO.getParams( - amount, - toAddress, - ); + // final txInfo = metaDTO.getTxInfo(state.type); + // final params = metaDTO.getParams( + // amount, + // toAddress, + // ); - final notificationsCubit = BlocProvider.of(context); - final appServiceCubit = BlocProvider.of(context); - - // print(metaDTO.getName()); - - await Transfer( - txInfo: txInfo, - params: params, - appService: appService, - context: context, - toAddress: toAddress, - password: password, - formKey: formKey, - notificationsCubit: notificationsCubit, - addHandler: appServiceCubit.addHandler, - symbols: metaDTO.getName(), - decimals: metaDTO.decimals, - amountNotification: amount, - ).sendFunds(); + // final notificationsCubit = BlocProvider.of(context); + // final appServiceCubit = BlocProvider.of(context); + + // // print(metaDTO.getName()); + + // await Transfer( + // txInfo: txInfo, + // params: params, + // appService: appService, + // context: context, + // toAddress: toAddress, + // password: password, + // formKey: formKey, + // notificationsCubit: notificationsCubit, + // addHandler: appServiceCubit.addHandler, + // symbols: metaDTO.getName(), + // decimals: metaDTO.decimals, + // amountNotification: amount, + // ).sendFunds(); } - void updateTransferType(final TransferType type) { + void updateTransferType(final TransactionOption type) { emit(state.copyWith(type: type)); } + + void addFromAddress() { + final newFromAddresses = List.from(state.fromAddresses); + newFromAddresses.add( + FromAddressData( + data: null, + passwordController: TextEditingController(), + ), + ); + + final newAmountsList = List.from(state.amounts); + newAmountsList.add( + SendAmountData( + amountController: TextEditingController(), + ), + ); + + emit( + state.copyWith( + fromAddresses: newFromAddresses, + amounts: newAmountsList, + ), + ); + } + + void addToAddress() { + final newToAddresses = List.from(state.toAddresses); + newToAddresses.add( + ToAddressData( + toAddressController: TextEditingController(), + ), + ); + + final newAmountsList = List.from(state.amounts); + newAmountsList.add( + SendAmountData( + amountController: TextEditingController(), + ), + ); + + emit( + state.copyWith( + toAddresses: newToAddresses, + amounts: newAmountsList, + ), + ); + } + + void changeChosenAccount( + final FromAddressData dataToChange, + final KeyPairData? acc, + ) { + if (dataToChange.data == acc) { + return; + } + print('1'); + final newFromAddresses = List.from(state.fromAddresses); + final newAddressData = dataToChange.copyWith(data: acc); + + newFromAddresses.replace(dataToChange, newAddressData); + + emit(state.copyWith(fromAddresses: newFromAddresses)); + } } +enum TransferScreenType { many_to_one, one_to_many } + @CopyWith() class TransferInfo { // Max avaliable balance in wallet in human-readable double format // final double balance; final TxFeeEstimateResult? fees; - final TransferType type; - final List<_FromAddressData> fromAddresses; - final List<_ToAddressData> toAddresses; + final TransactionOption type; + final List fromAddresses; + final List toAddresses; + final List amounts; const TransferInfo({ required this.fromAddresses, required this.toAddresses, required this.fees, required this.type, + required this.amounts, }); + + TransferScreenType get screenType => + fromAddresses.length >= toAddresses.length + ? TransferScreenType.many_to_one + : TransferScreenType.one_to_many; } -class _FromAddressData { - const _FromAddressData({ - required this.amount, - required this.balance, +// @CopyWith() +// class AddressData { +// const AddressData({ +// required this.data, +// required this.addressController, +// required this.passwordController, +// }); + +// final KeyPairData? data; +// final TextEditingController addressController; +// final TextEditingController passwordController; +// } + +@CopyWith() +class FromAddressData { + const FromAddressData({ required this.data, + required this.passwordController, }); final KeyPairData? data; - final double? amount; - final double? balance; + final TextEditingController passwordController; } -class _ToAddressData { - const _ToAddressData({ - required this.data, +@CopyWith() +class ToAddressData { + const ToAddressData({ + required this.toAddressController, }); - final KeyPairData? data; + + final TextEditingController toAddressController; +} + +@CopyWith() +class SendAmountData { + const SendAmountData({ + required this.amountController, + }); + + final TextEditingController amountController; + + // double? get amount => double.tryParse(amountController.text); } diff --git a/lib/features/wallet_screen/bloc/transfer_info_cubit.g.dart b/lib/features/wallet_screen/bloc/transfer_info_cubit.g.dart index 7bfd4e9b..3d277be9 100644 --- a/lib/features/wallet_screen/bloc/transfer_info_cubit.g.dart +++ b/lib/features/wallet_screen/bloc/transfer_info_cubit.g.dart @@ -7,13 +7,15 @@ part of 'transfer_info_cubit.dart'; // ************************************************************************** abstract class _$TransferInfoCWProxy { - TransferInfo fromAddresses(List<_FromAddressData> fromAddresses); + TransferInfo fromAddresses(List fromAddresses); - TransferInfo toAddresses(List<_ToAddressData> toAddresses); + TransferInfo toAddresses(List toAddresses); TransferInfo fees(TxFeeEstimateResult? fees); - TransferInfo type(TransferType type); + TransferInfo type(TransactionOption type); + + TransferInfo amounts(List amounts); /// This function **does support** nullification of nullable fields. All `null` values passed to `non-nullable` fields will be ignored. You can also use `TransferInfo(...).copyWith.fieldName(...)` to override fields one at a time with nullification support. /// @@ -22,10 +24,11 @@ abstract class _$TransferInfoCWProxy { /// TransferInfo(...).copyWith(id: 12, name: "My name") /// ```` TransferInfo call({ - List<_FromAddressData>? fromAddresses, - List<_ToAddressData>? toAddresses, + List? fromAddresses, + List? toAddresses, TxFeeEstimateResult? fees, - TransferType? type, + TransactionOption? type, + List? amounts, }); } @@ -36,18 +39,21 @@ class _$TransferInfoCWProxyImpl implements _$TransferInfoCWProxy { final TransferInfo _value; @override - TransferInfo fromAddresses(List<_FromAddressData> fromAddresses) => + TransferInfo fromAddresses(List fromAddresses) => this(fromAddresses: fromAddresses); @override - TransferInfo toAddresses(List<_ToAddressData> toAddresses) => + TransferInfo toAddresses(List toAddresses) => this(toAddresses: toAddresses); @override TransferInfo fees(TxFeeEstimateResult? fees) => this(fees: fees); @override - TransferInfo type(TransferType type) => this(type: type); + TransferInfo type(TransactionOption type) => this(type: type); + + @override + TransferInfo amounts(List amounts) => this(amounts: amounts); @override @@ -62,18 +68,19 @@ class _$TransferInfoCWProxyImpl implements _$TransferInfoCWProxy { Object? toAddresses = const $CopyWithPlaceholder(), Object? fees = const $CopyWithPlaceholder(), Object? type = const $CopyWithPlaceholder(), + Object? amounts = const $CopyWithPlaceholder(), }) { return TransferInfo( fromAddresses: fromAddresses == const $CopyWithPlaceholder() || fromAddresses == null ? _value.fromAddresses // ignore: cast_nullable_to_non_nullable - : fromAddresses as List<_FromAddressData>, + : fromAddresses as List, toAddresses: toAddresses == const $CopyWithPlaceholder() || toAddresses == null ? _value.toAddresses // ignore: cast_nullable_to_non_nullable - : toAddresses as List<_ToAddressData>, + : toAddresses as List, fees: fees == const $CopyWithPlaceholder() ? _value.fees // ignore: cast_nullable_to_non_nullable @@ -81,7 +88,11 @@ class _$TransferInfoCWProxyImpl implements _$TransferInfoCWProxy { type: type == const $CopyWithPlaceholder() || type == null ? _value.type // ignore: cast_nullable_to_non_nullable - : type as TransferType, + : type as TransactionOption, + amounts: amounts == const $CopyWithPlaceholder() || amounts == null + ? _value.amounts + // ignore: cast_nullable_to_non_nullable + : amounts as List, ); } } @@ -91,3 +102,170 @@ extension $TransferInfoCopyWith on TransferInfo { // ignore: library_private_types_in_public_api _$TransferInfoCWProxy get copyWith => _$TransferInfoCWProxyImpl(this); } + +abstract class _$FromAddressDataCWProxy { + FromAddressData data(KeyPairData? data); + + FromAddressData passwordController(TextEditingController passwordController); + + /// This function **does support** nullification of nullable fields. All `null` values passed to `non-nullable` fields will be ignored. You can also use `FromAddressData(...).copyWith.fieldName(...)` to override fields one at a time with nullification support. + /// + /// Usage + /// ```dart + /// FromAddressData(...).copyWith(id: 12, name: "My name") + /// ```` + FromAddressData call({ + KeyPairData? data, + TextEditingController? passwordController, + }); +} + +/// Proxy class for `copyWith` functionality. This is a callable class and can be used as follows: `instanceOfFromAddressData.copyWith(...)`. Additionally contains functions for specific fields e.g. `instanceOfFromAddressData.copyWith.fieldName(...)` +class _$FromAddressDataCWProxyImpl implements _$FromAddressDataCWProxy { + const _$FromAddressDataCWProxyImpl(this._value); + + final FromAddressData _value; + + @override + FromAddressData data(KeyPairData? data) => this(data: data); + + @override + FromAddressData passwordController( + TextEditingController passwordController) => + this(passwordController: passwordController); + + @override + + /// This function **does support** nullification of nullable fields. All `null` values passed to `non-nullable` fields will be ignored. You can also use `FromAddressData(...).copyWith.fieldName(...)` to override fields one at a time with nullification support. + /// + /// Usage + /// ```dart + /// FromAddressData(...).copyWith(id: 12, name: "My name") + /// ```` + FromAddressData call({ + Object? data = const $CopyWithPlaceholder(), + Object? passwordController = const $CopyWithPlaceholder(), + }) { + return FromAddressData( + data: data == const $CopyWithPlaceholder() + ? _value.data + // ignore: cast_nullable_to_non_nullable + : data as KeyPairData?, + passwordController: passwordController == const $CopyWithPlaceholder() || + passwordController == null + ? _value.passwordController + // ignore: cast_nullable_to_non_nullable + : passwordController as TextEditingController, + ); + } +} + +extension $FromAddressDataCopyWith on FromAddressData { + /// Returns a callable class that can be used as follows: `instanceOfFromAddressData.copyWith(...)` or like so:`instanceOfFromAddressData.copyWith.fieldName(...)`. + // ignore: library_private_types_in_public_api + _$FromAddressDataCWProxy get copyWith => _$FromAddressDataCWProxyImpl(this); +} + +abstract class _$ToAddressDataCWProxy { + ToAddressData toAddressController(TextEditingController toAddressController); + + /// This function **does support** nullification of nullable fields. All `null` values passed to `non-nullable` fields will be ignored. You can also use `ToAddressData(...).copyWith.fieldName(...)` to override fields one at a time with nullification support. + /// + /// Usage + /// ```dart + /// ToAddressData(...).copyWith(id: 12, name: "My name") + /// ```` + ToAddressData call({ + TextEditingController? toAddressController, + }); +} + +/// Proxy class for `copyWith` functionality. This is a callable class and can be used as follows: `instanceOfToAddressData.copyWith(...)`. Additionally contains functions for specific fields e.g. `instanceOfToAddressData.copyWith.fieldName(...)` +class _$ToAddressDataCWProxyImpl implements _$ToAddressDataCWProxy { + const _$ToAddressDataCWProxyImpl(this._value); + + final ToAddressData _value; + + @override + ToAddressData toAddressController( + TextEditingController toAddressController) => + this(toAddressController: toAddressController); + + @override + + /// This function **does support** nullification of nullable fields. All `null` values passed to `non-nullable` fields will be ignored. You can also use `ToAddressData(...).copyWith.fieldName(...)` to override fields one at a time with nullification support. + /// + /// Usage + /// ```dart + /// ToAddressData(...).copyWith(id: 12, name: "My name") + /// ```` + ToAddressData call({ + Object? toAddressController = const $CopyWithPlaceholder(), + }) { + return ToAddressData( + toAddressController: + toAddressController == const $CopyWithPlaceholder() || + toAddressController == null + ? _value.toAddressController + // ignore: cast_nullable_to_non_nullable + : toAddressController as TextEditingController, + ); + } +} + +extension $ToAddressDataCopyWith on ToAddressData { + /// Returns a callable class that can be used as follows: `instanceOfToAddressData.copyWith(...)` or like so:`instanceOfToAddressData.copyWith.fieldName(...)`. + // ignore: library_private_types_in_public_api + _$ToAddressDataCWProxy get copyWith => _$ToAddressDataCWProxyImpl(this); +} + +abstract class _$SendAmountDataCWProxy { + SendAmountData amountController(TextEditingController amountController); + + /// This function **does support** nullification of nullable fields. All `null` values passed to `non-nullable` fields will be ignored. You can also use `SendAmountData(...).copyWith.fieldName(...)` to override fields one at a time with nullification support. + /// + /// Usage + /// ```dart + /// SendAmountData(...).copyWith(id: 12, name: "My name") + /// ```` + SendAmountData call({ + TextEditingController? amountController, + }); +} + +/// Proxy class for `copyWith` functionality. This is a callable class and can be used as follows: `instanceOfSendAmountData.copyWith(...)`. Additionally contains functions for specific fields e.g. `instanceOfSendAmountData.copyWith.fieldName(...)` +class _$SendAmountDataCWProxyImpl implements _$SendAmountDataCWProxy { + const _$SendAmountDataCWProxyImpl(this._value); + + final SendAmountData _value; + + @override + SendAmountData amountController(TextEditingController amountController) => + this(amountController: amountController); + + @override + + /// This function **does support** nullification of nullable fields. All `null` values passed to `non-nullable` fields will be ignored. You can also use `SendAmountData(...).copyWith.fieldName(...)` to override fields one at a time with nullification support. + /// + /// Usage + /// ```dart + /// SendAmountData(...).copyWith(id: 12, name: "My name") + /// ```` + SendAmountData call({ + Object? amountController = const $CopyWithPlaceholder(), + }) { + return SendAmountData( + amountController: amountController == const $CopyWithPlaceholder() || + amountController == null + ? _value.amountController + // ignore: cast_nullable_to_non_nullable + : amountController as TextEditingController, + ); + } +} + +extension $SendAmountDataCopyWith on SendAmountData { + /// Returns a callable class that can be used as follows: `instanceOfSendAmountData.copyWith(...)` or like so:`instanceOfSendAmountData.copyWith.fieldName(...)`. + // ignore: library_private_types_in_public_api + _$SendAmountDataCWProxy get copyWith => _$SendAmountDataCWProxyImpl(this); +} diff --git a/lib/features/wallet_screen/domain/entities/transfer.dart b/lib/features/wallet_screen/domain/entities/transfer.dart index de14346d..d607fbfc 100644 --- a/lib/features/wallet_screen/domain/entities/transfer.dart +++ b/lib/features/wallet_screen/domain/entities/transfer.dart @@ -118,15 +118,14 @@ class Transfer { // notificationsCubit.replace(tmpN, readN); // tmpN = readN; - print('Broadcast'); + debugPrint('Broadcast'); default: - print(p0); + debugPrint(p0); } }, msgIdCallback: (final String msgId) { - print('SET MSG ID'); - print(msgId); + debugPrint('SET MSG ID $msgId'); addHandler( msgId, (final String p0) { @@ -142,13 +141,9 @@ class Transfer { }, ); }, - uidCallback: (final String msgId) { - print('SET UID'); - print(msgId); - }, ); // final b = 1 + 1; - print('Finished'); + // print('Finished'); } on Object catch (e) { // print('aaaaaaaaaaaa'); // final a = globalContext.router.stack; @@ -157,7 +152,7 @@ class Transfer { final ___ = context.router.stack; DefaultLoadingDialog.hide(globalContext); // DIALOG WAS NOT CLOSED - } on Object catch (e) { + } on Object catch (_) { // DIALOG WAS CLOSED debugPrint('dialog was closed'); } diff --git a/lib/features/wallet_screen/domain/entities/transfer_meta_dto.dart b/lib/features/wallet_screen/domain/entities/transfer_meta_dto.dart index 402f8bf1..bf02dd73 100644 --- a/lib/features/wallet_screen/domain/entities/transfer_meta_dto.dart +++ b/lib/features/wallet_screen/domain/entities/transfer_meta_dto.dart @@ -9,107 +9,133 @@ import 'package:threedpass/core/polkawallet/utils/tx_info.dart'; abstract class TransferMetaDTO { const TransferMetaDTO(); MetaInfoType get type; + String get name; + // TxInfoData getTxInfo(final TransferType transferType); - double getBalance(); - String getName(); - TxInfoData getTxInfo(final TransferType transferType); + // List getParams( + // final String? amount, + // final String toAddress, + // ); - List getParams( - final String? amount, - final String toAddress, - ); - - int get decimals; + // int get decimals; } class CoinsTransferMetaDTO extends TransferMetaDTO { - final String coinName; - final CoinsTransferTx txInfoValue; - final AppService appService; - - CoinsTransferMetaDTO({ - required this.coinName, - required this.appService, - }) : txInfoValue = CoinsTransferTx( - appService: appService, - ); - - @override - MetaInfoType get type => MetaInfoType.coin; - - @override - double getBalance() { - return BalanceUtils.balanceToDouble( - appService.chosenAccountBalance.value.availableBalance as String, - appService.networkStateData.safeDecimals, - ); - } - - @override - int get decimals => appService.networkStateData.safeDecimals; - - @override - String getName() { - return coinName; - } + const CoinsTransferMetaDTO({ + required this.name, + }); @override - TxInfoData getTxInfo(final TransferType transferType) { - return txInfoValue.txInfo(transferType); - } + final String name; @override - List getParams( - final String? amount, - final String toAddress, - ) { - return txInfoValue.params(amount, toAddress); - } + final MetaInfoType type = MetaInfoType.coin; } class AssetTransferMetaDTO extends TransferMetaDTO { - final TokenBalanceData tokenBalanceData; - final AssetsTransferTx txInfoValue; + const AssetTransferMetaDTO({ + required this.name, + required this.tokenId, + }); - AssetTransferMetaDTO({ - required this.tokenBalanceData, - required final AppService appService, - }) : txInfoValue = AssetsTransferTx( - appService: appService, - tokenBalanceData: tokenBalanceData, - ); + final int tokenId; @override - MetaInfoType get type => MetaInfoType.asset; + final String name; @override - double getBalance() { - return BalanceUtils.balanceToDouble( - tokenBalanceData.amount!, - tokenBalanceData.decimals ?? 12, - ); - } - - @override - String getName() { - return tokenBalanceData.symbol ?? ''; - } - - @override - TxInfoData getTxInfo(final TransferType transferType) { - return txInfoValue.txInfo(transferType); - } - - @override - int get decimals => tokenBalanceData.decimals ?? 12; - - @override - List getParams( - final String? amount, - final String toAddress, - ) { - return txInfoValue.params(amount, toAddress); - } + final MetaInfoType type = MetaInfoType.asset; } +// class CoinsTransferMetaDTO extends TransferMetaDTO { +// final String coinName; +// final CoinsTransferTx txInfoValue; +// final AppService appService; + +// CoinsTransferMetaDTO({ +// required this.coinName, +// required this.appService, +// }) : txInfoValue = CoinsTransferTx( +// appService: appService, +// ); + +// @override +// MetaInfoType get type => MetaInfoType.coin; + +// @override +// double getBalance() { +// appService.plugin.sdk.api.account.queryBalance(address) +// return BalanceUtils.balanceToDouble( +// appService.chosenAccountBalance.value.availableBalance as String, +// appService.networkStateData.safeDecimals, +// ); +// } + +// @override +// int get decimals => appService.networkStateData.safeDecimals; + +// @override +// String getName() { +// return coinName; +// } + +// @override +// TxInfoData getTxInfo(final TransferType transferType) { +// return txInfoValue.txInfo(transferType); +// } + +// @override +// List getParams( +// final String? amount, +// final String toAddress, +// ) { +// return txInfoValue.params(amount, toAddress); +// } +// } + +// class AssetTransferMetaDTO extends TransferMetaDTO { +// final TokenBalanceData tokenBalanceData; +// final AssetsTransferTx txInfoValue; + +// AssetTransferMetaDTO({ +// required this.tokenBalanceData, +// required final AppService appService, +// }) : txInfoValue = AssetsTransferTx( +// appService: appService, +// tokenBalanceData: tokenBalanceData, +// ); + +// @override +// MetaInfoType get type => MetaInfoType.asset; + +// @override +// double getBalance() { +// return BalanceUtils.balanceToDouble( +// tokenBalanceData.amount!, +// tokenBalanceData.decimals ?? 12, +// ); +// } + +// @override +// String getName() { +// return tokenBalanceData.symbol ?? ''; +// } + +// @override +// TxInfoData getTxInfo(final TransferType transferType) { +// return txInfoValue.txInfo(transferType); +// } + +// @override +// int get decimals => tokenBalanceData.decimals ?? 12; + +// @override +// List getParams( +// final String? amount, +// final String toAddress, +// ) { +// return txInfoValue.params(amount, toAddress); +// } +// } + enum MetaInfoType { asset, coin } diff --git a/lib/features/wallet_screen/presentation/assets_page/assets_page.dart b/lib/features/wallet_screen/presentation/assets_page/assets_page.dart index 5fe83f55..a9006ce9 100644 --- a/lib/features/wallet_screen/presentation/assets_page/assets_page.dart +++ b/lib/features/wallet_screen/presentation/assets_page/assets_page.dart @@ -22,7 +22,6 @@ class AssetsPage extends StatelessWidget { backgroundColor: theme.customColors.scaffoldBackground, appBar: AssetPageAppbar( account: state.keyring.current, - themeData: theme, ), drawer: AccountsDrawer( appServiceCubit: BlocProvider.of(context), diff --git a/lib/features/wallet_screen/presentation/assets_page/widgets/asset_page_appbar.dart b/lib/features/wallet_screen/presentation/assets_page/widgets/asset_page_appbar.dart index 9093f6e3..9a4f722e 100644 --- a/lib/features/wallet_screen/presentation/assets_page/widgets/asset_page_appbar.dart +++ b/lib/features/wallet_screen/presentation/assets_page/widgets/asset_page_appbar.dart @@ -8,24 +8,18 @@ import 'package:threedpass/core/theme/d3p_special_styles.dart'; import 'package:threedpass/core/utils/copy_and_notify.dart'; import 'package:threedpass/core/utils/formatters.dart'; import 'package:threedpass/core/widgets/buttons/icon_button.dart'; +import 'package:threedpass/core/widgets/paddings.dart'; import 'package:threedpass/features/wallet_screen/presentation/assets_page/widgets/notifications_icon_button.dart'; class AssetPageAppbar extends AppBar { AssetPageAppbar({ required final KeyPairData account, - required final ThemeData themeData, final Key? key, }) : super( key: key, backgroundColor: const D3pAppBarTheme().backgroundColor, centerTitle: true, - leading: Builder( - builder: (final context) => D3pIconButton( - iconData: Icons.switch_account_rounded, - iconColor: themeData.customColors.appBarButton, - onPressed: () => Scaffold.of(context).openDrawer(), - ), - ), + leading: const _SmartLeadingBackButton(), title: SizedBox( height: kToolbarHeight, child: Row( @@ -36,38 +30,13 @@ class AssetPageAppbar extends AppBar { svg: account.icon, ), const SizedBox(width: 16), - Column( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - Text( - Fmt.shorterAddress(account.address), - style: themeData.customTextStyles.accountAddress, - ), - const SizedBox(height: 4), - Text( - account.name ?? 'Anonymous', - style: themeData.customTextStyles.accountName, - ), - ], + _AccountName( + accountAddress: account.address, + accountName: account.name, ), const SizedBox(width: 16), - Container( - color: Colors.red, - width: D3pAddressIcon.defaultSize, - child: Align( - alignment: Alignment.center, - child: D3pIconButton( - emptyContraints: true, - iconData: Icons.copy, - size: 20, - iconColor: themeData.customColors.appBarButton, - onPressed: () => copyAndNotify( - textToCopy: account.address!, - textToShow: 'address_copied_to_clipboard'.tr(), - ), - ), - ), + _CopyButton( + accountAddress: account.address, ), ], ), @@ -77,3 +46,82 @@ class AssetPageAppbar extends AppBar { ], ); } + +class _SmartLeadingBackButton extends StatelessWidget { + const _SmartLeadingBackButton(); + + @override + Widget build(final BuildContext context) { + final theme = Theme.of(context); + + return D3pIconButton( + iconData: Icons.switch_account_rounded, + iconColor: theme.customColors.appBarButton, + onPressed: () => Scaffold.of(context).openDrawer(), + ); + } +} + +class _AccountName extends StatelessWidget { + const _AccountName({ + required this.accountAddress, + required this.accountName, + }); + + final String? accountName; + final String? accountAddress; + + @override + Widget build(final BuildContext context) { + final theme = Theme.of(context); + + return Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Text( + Fmt.shorterAddress(accountAddress), + style: theme.customTextStyles.accountAddress, + ), + const SizedBoxH4(), + Text( + accountName ?? 'Anonymous', + style: theme.customTextStyles.accountName, + ), + ], + ); + } +} + +class _CopyButton extends StatelessWidget { + const _CopyButton({ + required this.accountAddress, + }); + + final String? accountAddress; + + @override + Widget build(final BuildContext context) { + final theme = Theme.of(context); + + return SizedBox( + // color: Colors.red, + width: D3pAddressIcon.defaultSize, + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + D3pIconButton( + emptyContraints: true, + iconData: Icons.copy, + size: 20, + iconColor: theme.customColors.appBarButton, + onPressed: () => copyAndNotify( + textToCopy: accountAddress ?? '', + textToShow: 'address_copied_to_clipboard'.tr(), + ), + ), + ], + ), + ); + } +} diff --git a/lib/features/wallet_screen/presentation/assets_page/widgets/buttons_panel.dart b/lib/features/wallet_screen/presentation/assets_page/widgets/buttons_panel.dart index 3693899f..4425292d 100644 --- a/lib/features/wallet_screen/presentation/assets_page/widgets/buttons_panel.dart +++ b/lib/features/wallet_screen/presentation/assets_page/widgets/buttons_panel.dart @@ -9,9 +9,10 @@ class AssetPageButtonsPanel extends StatelessWidget { Widget build(final BuildContext context) { return const Row( mainAxisAlignment: MainAxisAlignment.center, + mainAxisSize: MainAxisSize.min, children: [ CoinTransferButton(), - SizedBox(width: 16), + SizedBox(width: 8), RecieveButton(), ], ); diff --git a/lib/features/wallet_screen/presentation/assets_page/widgets/coin_transfer_button.dart b/lib/features/wallet_screen/presentation/assets_page/widgets/coin_transfer_button.dart index 52ff73e9..3b5b0b07 100644 --- a/lib/features/wallet_screen/presentation/assets_page/widgets/coin_transfer_button.dart +++ b/lib/features/wallet_screen/presentation/assets_page/widgets/coin_transfer_button.dart @@ -1,9 +1,8 @@ import 'package:auto_route/auto_route.dart'; -import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:threedpass/core/polkawallet/bloc/app_service_cubit.dart'; -import 'package:threedpass/core/theme/d3p_special_styles.dart'; +import 'package:threedpass/core/widgets/buttons/floating_action_button.dart'; import 'package:threedpass/features/wallet_screen/domain/entities/transfer_meta_dto.dart'; import 'package:threedpass/features/wallet_screen/presentation/widgets/is_account_ready_builder.dart'; import 'package:threedpass/router/router.gr.dart'; @@ -17,8 +16,7 @@ class CoinTransferButton extends StatelessWidget { context.router.push( TransferRouteWrapper( metadata: CoinsTransferMetaDTO( - coinName: appService.networkStateData.tokenSymbol?.first ?? '', - appService: appService, + name: appService.networkStateData.tokenSymbol?.first ?? '', ), ), ); @@ -26,16 +24,12 @@ class CoinTransferButton extends StatelessWidget { @override Widget build(final BuildContext context) { - final style = Theme.of(context).customTextStyles.d3pFloatingButton; - return IsAccountReadyBuilder( builder: (final BuildContext context, final bool isReady) { - return FloatingActionButton.extended( - icon: const Icon(Icons.arrow_upward_rounded), - label: Text( - 'transfer_coins_button_label'.tr(), - style: style, - ), + return D3pFloatingActionButton( + heroTag: 'transfer_coins_button_label', + text: 'transfer_coins_button_label', + icons: Icons.arrow_upward_rounded, onPressed: isReady ? () => onPressed(context) : null, ); }, diff --git a/lib/features/wallet_screen/presentation/assets_page/widgets/recieve_button.dart b/lib/features/wallet_screen/presentation/assets_page/widgets/recieve_button.dart index a93e5036..213d8730 100644 --- a/lib/features/wallet_screen/presentation/assets_page/widgets/recieve_button.dart +++ b/lib/features/wallet_screen/presentation/assets_page/widgets/recieve_button.dart @@ -1,7 +1,6 @@ import 'package:auto_route/auto_route.dart'; -import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; -import 'package:threedpass/core/theme/d3p_special_styles.dart'; +import 'package:threedpass/core/widgets/buttons/floating_action_button.dart'; import 'package:threedpass/router/router.gr.dart'; class RecieveButton extends StatelessWidget { @@ -13,14 +12,10 @@ class RecieveButton extends StatelessWidget { @override Widget build(final BuildContext context) { - final style = Theme.of(context).customTextStyles.d3pFloatingButton; - - return FloatingActionButton.extended( - icon: const Icon(Icons.arrow_downward_rounded), - label: Text( - 'recieve_coins_button_label'.tr(), - style: style, - ), + return D3pFloatingActionButton( + heroTag: 'recieve_coins_button_label', + text: 'recieve_coins_button_label', + icons: Icons.arrow_downward_rounded, onPressed: () => onPressed(context), ); } diff --git a/lib/features/wallet_screen/presentation/non_native_token_screen/presentation/widgets/asset_transfer_button.dart b/lib/features/wallet_screen/presentation/non_native_token_screen/presentation/widgets/asset_transfer_button.dart index ffcdb328..4de3e4f9 100644 --- a/lib/features/wallet_screen/presentation/non_native_token_screen/presentation/widgets/asset_transfer_button.dart +++ b/lib/features/wallet_screen/presentation/non_native_token_screen/presentation/widgets/asset_transfer_button.dart @@ -2,7 +2,7 @@ import 'package:auto_route/auto_route.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; -import 'package:threedpass/core/polkawallet/bloc/app_service_cubit.dart'; +import 'package:fluttertoast/fluttertoast.dart'; import 'package:threedpass/core/widgets/buttons/elevated_button.dart'; import 'package:threedpass/features/wallet_screen/domain/entities/transfer_meta_dto.dart'; import 'package:threedpass/features/wallet_screen/presentation/non_native_token_screen/bloc/assets_get_extrisincs_cubit.dart'; @@ -14,16 +14,20 @@ class AssetTransferButton extends StatelessWidget { void onPressed(final BuildContext context) { final tkd = BlocProvider.of(context).tokenBalanceData; - final appService = BlocProvider.of(context).state; - context.router.push( - TransferRouteWrapper( - metadata: AssetTransferMetaDTO( - tokenBalanceData: tkd, - appService: appService, + try { + context.router.push( + TransferRouteWrapper( + metadata: AssetTransferMetaDTO( + tokenId: int.parse(tkd.id!), + name: tkd.name ?? '', + ), ), - ), - ); + ); + } on Exception catch (e) { + Fluttertoast.showToast( + msg: "Can't open transfer screen, because $e"); // TODO TRANSLATE + } } @override diff --git a/lib/features/wallet_screen/presentation/transfer_page/transfer_page.dart b/lib/features/wallet_screen/presentation/transfer_page/transfer_page.dart index d3620be2..41d57514 100644 --- a/lib/features/wallet_screen/presentation/transfer_page/transfer_page.dart +++ b/lib/features/wallet_screen/presentation/transfer_page/transfer_page.dart @@ -4,27 +4,17 @@ import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:threedpass/core/polkawallet/app_service.dart'; import 'package:threedpass/core/polkawallet/bloc/app_service_cubit.dart'; -import 'package:threedpass/core/polkawallet/utils/balance_utils.dart'; -import 'package:threedpass/core/theme/d3p_colors.dart'; -import 'package:threedpass/core/theme/d3p_special_styles.dart'; -import 'package:threedpass/core/utils/formatters.dart'; -import 'package:threedpass/core/utils/validators.dart'; import 'package:threedpass/core/widgets/buttons/elevated_button.dart'; -import 'package:threedpass/core/widgets/buttons/text_button.dart'; import 'package:threedpass/core/widgets/d3p_scaffold.dart'; -import 'package:threedpass/core/widgets/input/textformfield/textformfield.dart'; import 'package:threedpass/core/widgets/paddings.dart'; import 'package:threedpass/features/wallet_screen/bloc/transfer_info_cubit.dart'; -import 'package:threedpass/features/wallet_screen/domain/entities/transfer_meta_dto.dart'; -import 'package:threedpass/features/wallet_screen/presentation/transfer_page/widgets/basic_transfer_block.dart'; -import 'package:threedpass/features/wallet_screen/presentation/transfer_page/widgets/basic_transfer_textfield.dart'; -import 'package:threedpass/features/wallet_screen/presentation/transfer_page/widgets/from_address_textfield.dart'; -import 'package:threedpass/features/wallet_screen/presentation/transfer_page/widgets/transfer_type_dropdown.dart'; +import 'package:threedpass/features/wallet_screen/presentation/transfer_page/widgets/add_from_card_row.dart'; +import 'package:threedpass/features/wallet_screen/presentation/transfer_page/widgets/add_to_card_row.dart'; +import 'package:threedpass/features/wallet_screen/presentation/transfer_page/widgets/froms_list_view.dart'; +import 'package:threedpass/features/wallet_screen/presentation/transfer_page/widgets/tos_list_view.dart'; +import 'package:threedpass/features/wallet_screen/presentation/transfer_page/widgets/transfer_type_switch.dart'; part './widgets/make_transfer_button.dart'; -part 'widgets/to_address_textfield.dart'; -part 'widgets/amount_textfield.dart'; -part 'widgets/password_textfield.dart'; @RoutePage() class TransferPage extends StatelessWidget { @@ -32,9 +22,6 @@ class TransferPage extends StatelessWidget { final Key? key, }) : super(key: key); - final toAddressController = TextEditingController(); - final amountController = TextEditingController(); - final passwordController = TextEditingController(); final _formKey = GlobalKey(); @override @@ -43,79 +30,69 @@ class TransferPage extends StatelessWidget { final transferInfo = BlocProvider.of(context); // appService.keyring. return D3pScaffold( - appbarTitle: - 'transfer_page_title'.tr() + ' ' + transferInfo.metaDTO.getName(), + appbarTitle: 'transfer_page_title'.tr() + ' ' + transferInfo.metaDTO.name, translateAppbar: false, - body: Column( + body: Stack( children: [ - Flexible( - child: SingleChildScrollView( - child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 8), - child: Form( - key: _formKey, - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - // const SizedBoxH16(), - SizedBoxH8(), - ListView.builder( - shrinkWrap: true, - physics: const NeverScrollableScrollPhysics(), - itemCount: transferInfo.state.fromAddresses.length, - itemBuilder: (context, index) => BasicTransferBlock( - child: Column( - children: [ - const FromAddressTextField(), - SizedBoxH4(), - _PasswordTextField( - passwordController: passwordController, - ), - SizedBoxH4(), - _AmountTextFieldBuilder( - amountController: amountController, - transferMetaDTO: transferInfo.metaDTO, - balance: transferInfo - .state.fromAddresses[index].balance ?? - 0, - ), - ], + SingleChildScrollView( + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 8), + child: Form( + key: _formKey, + child: BlocBuilder( + builder: (final context, final state) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const SizedBoxH8(), + + FromsListView( + transferInfo: state, + metaInfoType: transferInfo.metaDTO.type, + ), + + const AddFromCardRow(), + + const Align( + alignment: Alignment.center, + child: Icon( + Icons.arrow_downward_outlined, + size: 30, ), ), - ), - Align( - alignment: Alignment.center, - child: Icon( - Icons.arrow_downward_outlined, - size: 30, + // const SizedBoxH24(), + ToListView( + transferInfo: state, + metaInfoType: transferInfo.metaDTO.type, ), - ), - // const SizedBoxH24(), - _ToAddressTextField( - toAddressController: toAddressController, - ), - const SizedBoxH16(), + const AddToCardRow(), + + // const SizedBoxH16(), - const TransferTypeDropdown(), - // const SizedBox(height: 24), - // const FeesText(), - const SizedBox(height: 36), - ], - ), + const TransferTypeSwitch(), + // const SizedBox(height: 24), + // const FeesText(), + const SizedBox(height: 72), + ], + ); + }, ), ), ), ), - Padding( - padding: const EdgeInsets.only(bottom: 8), - child: _MakeTransferButton( - toAddressController: toAddressController, - amountController: amountController, - passwordController: passwordController, - formKey: _formKey, - appService: appService, + Align( + alignment: Alignment.bottomCenter, + child: Padding( + padding: const EdgeInsets.symmetric(vertical: 16, horizontal: 16), + child: _MakeTransferButton( + toAddressController: TextEditingController(), + amountController: TextEditingController(), + passwordController: TextEditingController(), + formKey: _formKey, + appService: appService, + ), ), ), ], diff --git a/lib/features/wallet_screen/presentation/transfer_page/widgets/add_card_basic.dart b/lib/features/wallet_screen/presentation/transfer_page/widgets/add_card_basic.dart new file mode 100644 index 00000000..9669a2e1 --- /dev/null +++ b/lib/features/wallet_screen/presentation/transfer_page/widgets/add_card_basic.dart @@ -0,0 +1,59 @@ +import 'package:easy_localization/easy_localization.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:threedpass/core/theme/d3p_special_styles.dart'; +import 'package:threedpass/core/widgets/buttons/icon_button.dart'; +import 'package:threedpass/features/wallet_screen/bloc/transfer_info_cubit.dart'; + +class AddCardRowBasic extends StatelessWidget { + const AddCardRowBasic({ + required this.onPressed, + required this.unlocalizedText, + required this.condition, + super.key, + }); + + final void Function() onPressed; + final String unlocalizedText; + final bool Function(TransferInfo state) condition; + + @override + Widget build(final BuildContext context) { + final textStyles = Theme.of(context).customTextStyles; + return BlocBuilder( + builder: (final context, final state) { + if (condition(state)) { + return Padding( + padding: const EdgeInsets.symmetric(vertical: 8), + child: Row( + children: [ + const Flexible( + flex: 1, + child: SizedBox( + width: double.infinity, + ), + ), + const SizedBox(width: 8), + D3pIconButton( + iconData: Icons.add_circle_outline_rounded, + onPressed: () => onPressed(), + emptyContraints: true, + ), + const SizedBox(width: 8), + Flexible( + flex: 1, + child: Text( + unlocalizedText.tr(), + style: textStyles.hintStyle, + ), + ), + ], + ), + ); + } else { + return const SizedBox(); + } + }, + ); + } +} diff --git a/lib/features/wallet_screen/presentation/transfer_page/widgets/add_from_card_row.dart b/lib/features/wallet_screen/presentation/transfer_page/widgets/add_from_card_row.dart new file mode 100644 index 00000000..a3a2869d --- /dev/null +++ b/lib/features/wallet_screen/presentation/transfer_page/widgets/add_from_card_row.dart @@ -0,0 +1,24 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:threedpass/features/wallet_screen/bloc/transfer_info_cubit.dart'; +import 'package:threedpass/features/wallet_screen/presentation/transfer_page/widgets/add_card_basic.dart'; + +class AddFromCardRow extends StatelessWidget { + const AddFromCardRow({ + super.key, + }); + + @override + Widget build(final BuildContext context) { + final transferInfoCubit = BlocProvider.of(context); + // print(transferInfoCubit.state.fromAddresses.length); + // print(transferInfoCubit.state.toAddresses.length); + + return AddCardRowBasic( + onPressed: () => transferInfoCubit.addFromAddress(), + unlocalizedText: 'add_account_from_label', + condition: (final state) => + state.screenType == TransferScreenType.many_to_one, + ); + } +} diff --git a/lib/features/wallet_screen/presentation/transfer_page/widgets/add_to_card_row.dart b/lib/features/wallet_screen/presentation/transfer_page/widgets/add_to_card_row.dart new file mode 100644 index 00000000..097aafcb --- /dev/null +++ b/lib/features/wallet_screen/presentation/transfer_page/widgets/add_to_card_row.dart @@ -0,0 +1,22 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:threedpass/features/wallet_screen/bloc/transfer_info_cubit.dart'; +import 'package:threedpass/features/wallet_screen/presentation/transfer_page/widgets/add_card_basic.dart'; + +class AddToCardRow extends StatelessWidget { + const AddToCardRow({ + super.key, + }); + + @override + Widget build(final BuildContext context) { + final transferInfoCubit = BlocProvider.of(context); + return AddCardRowBasic( + onPressed: () => transferInfoCubit.addToAddress(), + unlocalizedText: 'add_account_to_label', + condition: (final state) => + state.screenType == TransferScreenType.one_to_many || + state.fromAddresses.length == 1, + ); + } +} diff --git a/lib/features/wallet_screen/presentation/transfer_page/widgets/amount_textfield.dart b/lib/features/wallet_screen/presentation/transfer_page/widgets/amount_textfield.dart index aa148ada..cde5f812 100644 --- a/lib/features/wallet_screen/presentation/transfer_page/widgets/amount_textfield.dart +++ b/lib/features/wallet_screen/presentation/transfer_page/widgets/amount_textfield.dart @@ -1,15 +1,19 @@ -part of '../transfer_page.dart'; - -class _AmountTextFieldBuilder extends StatelessWidget { - const _AmountTextFieldBuilder({ +import 'package:easy_localization/easy_localization.dart'; +import 'package:flutter/material.dart'; +import 'package:threedpass/core/polkawallet/utils/balance_utils.dart'; +import 'package:threedpass/features/wallet_screen/domain/entities/transfer_meta_dto.dart'; +import 'package:threedpass/features/wallet_screen/presentation/transfer_page/widgets/basic_transfer_textfield.dart'; + +class AmountTextFieldBuilder extends StatelessWidget { + const AmountTextFieldBuilder({ required this.amountController, - required this.transferMetaDTO, + required this.transferType, required this.balance, final Key? key, }) : super(key: key); final TextEditingController amountController; - final TransferMetaDTO transferMetaDTO; + final MetaInfoType transferType; final double balance; @override @@ -17,7 +21,7 @@ class _AmountTextFieldBuilder extends StatelessWidget { return _AmountTextField( amountController: amountController, balance: balance, - transferMetaDTO: transferMetaDTO, + transferType: transferType, ); } } @@ -26,16 +30,16 @@ class _AmountTextField extends StatelessWidget { const _AmountTextField({ required this.amountController, required this.balance, - required this.transferMetaDTO, + required this.transferType, final Key? key, }) : super(key: key); final TextEditingController amountController; - final TransferMetaDTO transferMetaDTO; + final MetaInfoType transferType; final double balance; String? Function(String? v) validator() { - switch (transferMetaDTO.type) { + switch (transferType) { case MetaInfoType.coin: return _DoubleValidator(balance).amountValidator; case MetaInfoType.asset: diff --git a/lib/features/wallet_screen/presentation/transfer_page/widgets/from_address_textfield.dart b/lib/features/wallet_screen/presentation/transfer_page/widgets/from_address_textfield.dart index 4352f3c8..4a912948 100644 --- a/lib/features/wallet_screen/presentation/transfer_page/widgets/from_address_textfield.dart +++ b/lib/features/wallet_screen/presentation/transfer_page/widgets/from_address_textfield.dart @@ -2,21 +2,30 @@ import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_platform_widgets/flutter_platform_widgets.dart'; +import 'package:polkawallet_sdk/storage/types/keyPairData.dart'; import 'package:threedpass/core/polkawallet/bloc/app_service_cubit.dart'; import 'package:threedpass/core/theme/d3p_colors.dart'; +import 'package:threedpass/core/theme/d3p_special_colors.dart'; import 'package:threedpass/core/theme/d3p_special_styles.dart'; import 'package:threedpass/core/utils/formatters.dart'; import 'package:threedpass/core/widgets/buttons/elevated_button.dart'; import 'package:threedpass/core/widgets/buttons/enum_button.dart'; import 'package:threedpass/core/widgets/paddings.dart'; +import 'package:threedpass/core/widgets/text/d3p_body_medium_text.dart'; +import 'package:threedpass/features/wallet_screen/bloc/transfer_info_cubit.dart'; class FromAddressTextField extends StatelessWidget { - const FromAddressTextField({final Key? key}) : super(key: key); + const FromAddressTextField({ + required this.data, + super.key, + }); + + final FromAddressData data; @override Widget build(final BuildContext context) { - final appService = BlocProvider.of(context).state; - final theme = Theme.of(context); + // final appService = BlocProvider.of(context).state; + // final theme = Theme.of(context); // Colors from https://github.com/flutter/flutter/blob/936763f58963ef3dd103986fc232310c43360344/packages/flutter/lib/src/material/input_decorator.dart#L4561 // switch (Theme.of(context).brightness) { @@ -26,13 +35,15 @@ class FromAddressTextField extends StatelessWidget { // return const Color(0x05000000) ; // } final textStyle = Theme.of(context).customTextStyles; + final colors = Theme.of(context).customColors; + // TODO MAKE BUTTON TO COPY PASSWORD FROM TOP ACCOUNT return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( 'from_address_label'.tr(), - style: textStyle.d3pBodySmall.copyWith(color: D3pColors.disabled), + style: textStyle.hintStyle, ), const SizedBoxH4(), SizedBox( @@ -40,15 +51,18 @@ class FromAddressTextField extends StatelessWidget { child: D3pElevatedButton( text: null, onPressed: () => openDialog(context), - backgroundColor: const Color(0x0DFFFFFF), + backgroundColor: colors.defaultInputColor, elevation: 0, childAlignment: MainAxisAlignment.start, textStyle: textStyle.d3pBodyMedium, - child: const Row( + child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - Text('Account name'), - Icon(Icons.keyboard_arrow_down_rounded), + _ButtonText(data: data.data), + Icon( + Icons.keyboard_arrow_down_rounded, + color: colors.themeOpposite, + ), ], ), ), @@ -68,16 +82,18 @@ class FromAddressTextField extends StatelessWidget { } Future openDialog(final BuildContext context) { - final accounts = BlocProvider.of(context) + final allAccounts = BlocProvider.of(context) .state .keyring .allAccounts; + final chosenFromAddresses = + BlocProvider.of(context).state.fromAddresses; - //BlocProvider.of(context).state.plugin.sdk.api.account.queryBalance + final accounts = AccountsList( + allAccounts: allAccounts, + chosenAccounts: chosenFromAddresses, + ).buildListToChoose(); - // Fmt.shorterAddress( - // appService.keyring.current.address, - // ), return showPlatformModalSheet( context: context, material: MaterialModalSheetData( @@ -98,7 +114,7 @@ class FromAddressTextField extends StatelessWidget { itemBuilder: (final context, final index) => EnumButton( text: null, isChosen: false, - onPressed: () {}, + onPressed: () => onAccountChoose(context, accounts[index]), child: _AccountChooseTileText( address: accounts[index].address, name: accounts[index].name, @@ -109,6 +125,33 @@ class FromAddressTextField extends StatelessWidget { ), ); } + + void onAccountChoose(final BuildContext context, final KeyPairData acc) { + final transferInfoCubit = BlocProvider.of(context); + transferInfoCubit.changeChosenAccount(data, acc); + Navigator.of(context).pop(); + } +} + +class _ButtonText extends StatelessWidget { + const _ButtonText({required this.data}); + final KeyPairData? data; + + @override + Widget build(final BuildContext context) { + if (data != null) { + return _AccountChooseTileText( + address: data?.address, + name: data?.name, + ); + } else { + final colors = Theme.of(context).customColors; + return D3pBodyMediumText( + 'from_select_account_title', + color: colors.themeOpposite, + ); + } + } } class _AccountChooseTileText extends StatelessWidget { @@ -149,3 +192,25 @@ class _AccountChooseTileText extends StatelessWidget { // return '${fixedName()}${shortAddress()}'; } } + +class AccountsList { + final List allAccounts; + final List chosenAccounts; + + const AccountsList({ + required this.allAccounts, + required this.chosenAccounts, + }); + + List buildListToChoose() { + final setOfChosen = {}; + for (final i in chosenAccounts) { + setOfChosen.add(i.data?.address ?? ''); + } + final newList = List.from(allAccounts); + + newList + .removeWhere((final element) => setOfChosen.contains(element.address)); + return newList; + } +} diff --git a/lib/features/wallet_screen/presentation/transfer_page/widgets/from_card_basic.dart b/lib/features/wallet_screen/presentation/transfer_page/widgets/from_card_basic.dart new file mode 100644 index 00000000..c521f7f2 --- /dev/null +++ b/lib/features/wallet_screen/presentation/transfer_page/widgets/from_card_basic.dart @@ -0,0 +1,29 @@ +import 'package:flutter/material.dart'; +import 'package:threedpass/core/widgets/paddings.dart'; +import 'package:threedpass/features/wallet_screen/bloc/transfer_info_cubit.dart'; +import 'package:threedpass/features/wallet_screen/presentation/transfer_page/widgets/from_address_textfield.dart'; +import 'package:threedpass/features/wallet_screen/presentation/transfer_page/widgets/password_textfield.dart'; + +class FromCardBasic extends StatelessWidget { + const FromCardBasic({ + required this.data, + super.key, + }); + + final FromAddressData data; + + @override + Widget build(final BuildContext context) { + return Column( + children: [ + FromAddressTextField( + data: data, + ), + const SizedBoxH4(), + PasswordTextField( + passwordController: data.passwordController, + ), + ], + ); + } +} diff --git a/lib/features/wallet_screen/presentation/transfer_page/widgets/from_card_many_to_one.dart b/lib/features/wallet_screen/presentation/transfer_page/widgets/from_card_many_to_one.dart new file mode 100644 index 00000000..033534ba --- /dev/null +++ b/lib/features/wallet_screen/presentation/transfer_page/widgets/from_card_many_to_one.dart @@ -0,0 +1,39 @@ +import 'package:flutter/material.dart'; +import 'package:threedpass/core/widgets/paddings.dart'; +import 'package:threedpass/features/wallet_screen/bloc/transfer_info_cubit.dart'; +import 'package:threedpass/features/wallet_screen/domain/entities/transfer_meta_dto.dart'; +import 'package:threedpass/features/wallet_screen/presentation/transfer_page/widgets/amount_textfield.dart'; +import 'package:threedpass/features/wallet_screen/presentation/transfer_page/widgets/basic_transfer_block.dart'; +import 'package:threedpass/features/wallet_screen/presentation/transfer_page/widgets/from_card_basic.dart'; + +class FromCardManyToOne extends StatelessWidget { + const FromCardManyToOne({ + required this.data, + required this.sendAmountData, + required this.metaInfoType, + super.key, + }); + + final FromAddressData data; + final MetaInfoType metaInfoType; + final SendAmountData sendAmountData; + + @override + Widget build(final BuildContext context) { + return BasicTransferBlock( + child: Column( + children: [ + FromCardBasic( + data: data, + ), + const SizedBoxH4(), + AmountTextFieldBuilder( + amountController: sendAmountData.amountController, + transferType: metaInfoType, + balance: 0, // TODO + ), + ], + ), + ); + } +} diff --git a/lib/features/wallet_screen/presentation/transfer_page/widgets/from_card_one_to_many.dart b/lib/features/wallet_screen/presentation/transfer_page/widgets/from_card_one_to_many.dart new file mode 100644 index 00000000..2a1c4aae --- /dev/null +++ b/lib/features/wallet_screen/presentation/transfer_page/widgets/from_card_one_to_many.dart @@ -0,0 +1,22 @@ +import 'package:flutter/material.dart'; +import 'package:threedpass/features/wallet_screen/bloc/transfer_info_cubit.dart'; +import 'package:threedpass/features/wallet_screen/presentation/transfer_page/widgets/basic_transfer_block.dart'; +import 'package:threedpass/features/wallet_screen/presentation/transfer_page/widgets/from_card_basic.dart'; + +class FromCardOneToMany extends StatelessWidget { + const FromCardOneToMany({ + required this.data, + super.key, + }); + + final FromAddressData data; + + @override + Widget build(final BuildContext context) { + return BasicTransferBlock( + child: FromCardBasic( + data: data, + ), + ); + } +} diff --git a/lib/features/wallet_screen/presentation/transfer_page/widgets/froms_list_view.dart b/lib/features/wallet_screen/presentation/transfer_page/widgets/froms_list_view.dart new file mode 100644 index 00000000..b25b1ef9 --- /dev/null +++ b/lib/features/wallet_screen/presentation/transfer_page/widgets/froms_list_view.dart @@ -0,0 +1,36 @@ +import 'package:flutter/material.dart'; +import 'package:threedpass/features/wallet_screen/bloc/transfer_info_cubit.dart'; +import 'package:threedpass/features/wallet_screen/domain/entities/transfer_meta_dto.dart'; +import 'package:threedpass/features/wallet_screen/presentation/transfer_page/widgets/from_card_many_to_one.dart'; +import 'package:threedpass/features/wallet_screen/presentation/transfer_page/widgets/from_card_one_to_many.dart'; + +/// List of cards send FROM +class FromsListView extends StatelessWidget { + const FromsListView({ + required this.transferInfo, + required this.metaInfoType, + super.key, + }); + + final TransferInfo transferInfo; + final MetaInfoType metaInfoType; + + @override + Widget build(final BuildContext context) { + return ListView.builder( + shrinkWrap: true, + physics: const NeverScrollableScrollPhysics(), + itemCount: transferInfo.fromAddresses.length, + itemBuilder: (final context, final index) => + transferInfo.screenType == TransferScreenType.many_to_one + ? FromCardManyToOne( + data: transferInfo.fromAddresses[index], + sendAmountData: transferInfo.amounts[index], + metaInfoType: metaInfoType, + ) + : FromCardOneToMany( + data: transferInfo.fromAddresses[index], + ), + ); + } +} diff --git a/lib/features/wallet_screen/presentation/transfer_page/widgets/make_transfer_button.dart b/lib/features/wallet_screen/presentation/transfer_page/widgets/make_transfer_button.dart index e4c16f8e..83705c36 100644 --- a/lib/features/wallet_screen/presentation/transfer_page/widgets/make_transfer_button.dart +++ b/lib/features/wallet_screen/presentation/transfer_page/widgets/make_transfer_button.dart @@ -32,7 +32,6 @@ class _MakeTransferButton extends StatelessWidget { Widget build(final BuildContext context) { return BlocBuilder( builder: (final context, final state) => D3pElevatedButton( - padding: const EdgeInsets.symmetric(horizontal: 16), text: 'make_transfer_label'.tr(), onPressed: state != null ? () => onPressed(context) diff --git a/lib/features/wallet_screen/presentation/transfer_page/widgets/password_textfield.dart b/lib/features/wallet_screen/presentation/transfer_page/widgets/password_textfield.dart index f577b296..29dcc1f3 100644 --- a/lib/features/wallet_screen/presentation/transfer_page/widgets/password_textfield.dart +++ b/lib/features/wallet_screen/presentation/transfer_page/widgets/password_textfield.dart @@ -1,7 +1,10 @@ -part of '../transfer_page.dart'; +import 'package:easy_localization/easy_localization.dart'; +import 'package:flutter/material.dart'; +import 'package:threedpass/core/utils/validators.dart'; +import 'package:threedpass/features/wallet_screen/presentation/transfer_page/widgets/basic_transfer_textfield.dart'; -class _PasswordTextField extends StatelessWidget { - const _PasswordTextField({ +class PasswordTextField extends StatelessWidget { + const PasswordTextField({ required this.passwordController, final Key? key, }) : super(key: key); diff --git a/lib/features/wallet_screen/presentation/transfer_page/widgets/to_address_textfield.dart b/lib/features/wallet_screen/presentation/transfer_page/widgets/to_address_textfield.dart index 8ee340ea..4c83998d 100644 --- a/lib/features/wallet_screen/presentation/transfer_page/widgets/to_address_textfield.dart +++ b/lib/features/wallet_screen/presentation/transfer_page/widgets/to_address_textfield.dart @@ -1,7 +1,9 @@ -part of '../transfer_page.dart'; +import 'package:easy_localization/easy_localization.dart'; +import 'package:flutter/material.dart'; +import 'package:threedpass/features/wallet_screen/presentation/transfer_page/widgets/basic_transfer_textfield.dart'; -class _ToAddressTextField extends StatelessWidget { - const _ToAddressTextField({ +class ToAddressTextField extends StatelessWidget { + const ToAddressTextField({ required this.toAddressController, final Key? key, }) : super(key: key); @@ -10,22 +12,11 @@ class _ToAddressTextField extends StatelessWidget { @override Widget build(final BuildContext context) { - return Card( - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.all(Radius.circular(16)), - ), - child: Padding( - padding: EdgeInsets.symmetric( - horizontal: 16, - vertical: 16, - ), - child: BasicTransferTextField( - labelText: 'to_address_label'.tr(), - controller: toAddressController, - maxLines: 1, - hintText: 'to_address_hint'.tr(), - ), - ), + return BasicTransferTextField( + labelText: 'to_address_label'.tr(), + controller: toAddressController, + maxLines: 1, + hintText: 'to_address_hint'.tr(), ); } } diff --git a/lib/features/wallet_screen/presentation/transfer_page/widgets/to_card_basic.dart b/lib/features/wallet_screen/presentation/transfer_page/widgets/to_card_basic.dart new file mode 100644 index 00000000..cc534039 --- /dev/null +++ b/lib/features/wallet_screen/presentation/transfer_page/widgets/to_card_basic.dart @@ -0,0 +1,19 @@ +import 'package:flutter/material.dart'; +import 'package:threedpass/features/wallet_screen/bloc/transfer_info_cubit.dart'; +import 'package:threedpass/features/wallet_screen/presentation/transfer_page/widgets/to_address_textfield.dart'; + +class ToCardBasic extends StatelessWidget { + const ToCardBasic({ + required this.data, + super.key, + }); + + final ToAddressData data; + + @override + Widget build(final BuildContext context) { + return ToAddressTextField( + toAddressController: data.toAddressController, + ); + } +} diff --git a/lib/features/wallet_screen/presentation/transfer_page/widgets/to_card_many_to_one.dart b/lib/features/wallet_screen/presentation/transfer_page/widgets/to_card_many_to_one.dart new file mode 100644 index 00000000..8e631115 --- /dev/null +++ b/lib/features/wallet_screen/presentation/transfer_page/widgets/to_card_many_to_one.dart @@ -0,0 +1,22 @@ +import 'package:flutter/material.dart'; +import 'package:threedpass/features/wallet_screen/bloc/transfer_info_cubit.dart'; +import 'package:threedpass/features/wallet_screen/presentation/transfer_page/widgets/basic_transfer_block.dart'; +import 'package:threedpass/features/wallet_screen/presentation/transfer_page/widgets/to_card_basic.dart'; + +class ToCardManyToOne extends StatelessWidget { + const ToCardManyToOne({ + required this.data, + super.key, + }); + + final ToAddressData data; + + @override + Widget build(final BuildContext context) { + return BasicTransferBlock( + child: ToCardBasic( + data: data, + ), + ); + } +} diff --git a/lib/features/wallet_screen/presentation/transfer_page/widgets/to_card_one_to_many.dart b/lib/features/wallet_screen/presentation/transfer_page/widgets/to_card_one_to_many.dart new file mode 100644 index 00000000..65b2b37b --- /dev/null +++ b/lib/features/wallet_screen/presentation/transfer_page/widgets/to_card_one_to_many.dart @@ -0,0 +1,39 @@ +import 'package:flutter/material.dart'; +import 'package:threedpass/core/widgets/paddings.dart'; +import 'package:threedpass/features/wallet_screen/bloc/transfer_info_cubit.dart'; +import 'package:threedpass/features/wallet_screen/domain/entities/transfer_meta_dto.dart'; +import 'package:threedpass/features/wallet_screen/presentation/transfer_page/widgets/amount_textfield.dart'; +import 'package:threedpass/features/wallet_screen/presentation/transfer_page/widgets/basic_transfer_block.dart'; +import 'package:threedpass/features/wallet_screen/presentation/transfer_page/widgets/to_card_basic.dart'; + +class ToCardOneToMany extends StatelessWidget { + const ToCardOneToMany({ + required this.data, + required this.sendAmountData, + required this.metaInfoType, + super.key, + }); + + final ToAddressData data; + final MetaInfoType metaInfoType; + final SendAmountData sendAmountData; + + @override + Widget build(final BuildContext context) { + return BasicTransferBlock( + child: Column( + children: [ + ToCardBasic( + data: data, + ), + const SizedBoxH4(), + AmountTextFieldBuilder( + amountController: sendAmountData.amountController, + transferType: metaInfoType, + balance: 0, // TODO + ), + ], + ), + ); + } +} diff --git a/lib/features/wallet_screen/presentation/transfer_page/widgets/tos_list_view.dart b/lib/features/wallet_screen/presentation/transfer_page/widgets/tos_list_view.dart new file mode 100644 index 00000000..aa8513b0 --- /dev/null +++ b/lib/features/wallet_screen/presentation/transfer_page/widgets/tos_list_view.dart @@ -0,0 +1,36 @@ +import 'package:flutter/material.dart'; +import 'package:threedpass/features/wallet_screen/bloc/transfer_info_cubit.dart'; +import 'package:threedpass/features/wallet_screen/domain/entities/transfer_meta_dto.dart'; +import 'package:threedpass/features/wallet_screen/presentation/transfer_page/widgets/to_card_many_to_one.dart'; +import 'package:threedpass/features/wallet_screen/presentation/transfer_page/widgets/to_card_one_to_many.dart'; + +/// List of cards send TO +class ToListView extends StatelessWidget { + const ToListView({ + required this.transferInfo, + required this.metaInfoType, + super.key, + }); + + final TransferInfo transferInfo; + final MetaInfoType metaInfoType; + + @override + Widget build(final BuildContext context) { + return ListView.builder( + shrinkWrap: true, + physics: const NeverScrollableScrollPhysics(), + itemCount: transferInfo.toAddresses.length, + itemBuilder: (final context, final index) => + transferInfo.screenType == TransferScreenType.many_to_one + ? ToCardManyToOne( + data: transferInfo.toAddresses[index], + ) + : ToCardOneToMany( + data: transferInfo.toAddresses[index], + sendAmountData: transferInfo.amounts[index], + metaInfoType: metaInfoType, + ), + ); + } +} diff --git a/lib/features/wallet_screen/presentation/transfer_page/widgets/transfer_type_dropdown.dart b/lib/features/wallet_screen/presentation/transfer_page/widgets/transfer_type_switch.dart similarity index 76% rename from lib/features/wallet_screen/presentation/transfer_page/widgets/transfer_type_dropdown.dart rename to lib/features/wallet_screen/presentation/transfer_page/widgets/transfer_type_switch.dart index 9614b1a3..1cad783f 100644 --- a/lib/features/wallet_screen/presentation/transfer_page/widgets/transfer_type_dropdown.dart +++ b/lib/features/wallet_screen/presentation/transfer_page/widgets/transfer_type_switch.dart @@ -5,12 +5,12 @@ import 'package:threedpass/core/polkawallet/utils/transfer_type.dart'; import 'package:threedpass/core/widgets/input/switch_button.dart'; import 'package:threedpass/features/wallet_screen/bloc/transfer_info_cubit.dart'; -class TransferTypeDropdown extends StatelessWidget { - const TransferTypeDropdown({ +class TransferTypeSwitch extends StatelessWidget { + const TransferTypeSwitch({ final Key? key, }) : super(key: key); - void onChanged(final BuildContext context, final TransferType? value) { + void onChanged(final BuildContext context, final TransactionOption? value) { if (value != null) { BlocProvider.of(context).updateTransferType(value); } @@ -20,7 +20,7 @@ class TransferTypeDropdown extends StatelessWidget { Widget build(final BuildContext context) { final initialValue = BlocProvider.of(context).state.type == - TransferType.transferKeepAlive; + TransactionOption.transferKeepAlive; return Padding( padding: const EdgeInsets.symmetric(horizontal: 8), child: D3pSwitchButton( @@ -28,7 +28,9 @@ class TransferTypeDropdown extends StatelessWidget { helpText: 'transfer_keep_alive_help'.tr(), onChanged: (final value) => onChanged( context, - value ? TransferType.transferKeepAlive : TransferType.transfer, + value + ? TransactionOption.transferKeepAlive + : TransactionOption.transfer, ), text: 'choose_transfer_keep_alive'.tr(), ), diff --git a/packages/super_core/lib/list_extentions.dart b/packages/super_core/lib/list_extentions.dart new file mode 100644 index 00000000..009acd29 --- /dev/null +++ b/packages/super_core/lib/list_extentions.dart @@ -0,0 +1,14 @@ +extension ListExtensions on List { + bool replace(E element, E replacement) { + var found = false; + final len = length; + for (var i = 0; i < len; i++) { + if (element == this[i]) { + this[i] = replacement; + found = true; + } + } + + return found; + } +} diff --git a/packages/super_core/lib/super_core.dart b/packages/super_core/lib/super_core.dart index 754a8150..fbefff23 100644 --- a/packages/super_core/lib/super_core.dart +++ b/packages/super_core/lib/super_core.dart @@ -4,3 +4,4 @@ export 'either.dart'; export 'failure.dart'; export 'di_module.dart'; export 'to_map_string_dynamic.dart'; +export 'list_extentions.dart'; diff --git a/pubspec.lock b/pubspec.lock index 1c0a3fb9..1db1d98c 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -1151,8 +1151,8 @@ packages: dependency: "direct main" description: path: "." - ref: "7338432b20bbea4a4fe12d37df0fa9c5e572522a" - resolved-ref: "7338432b20bbea4a4fe12d37df0fa9c5e572522a" + ref: "0d130d746954219bd165c96906f971ec1c5556a8" + resolved-ref: "0d130d746954219bd165c96906f971ec1c5556a8" url: "https://github.com/L3odr0id/polkawallet_sdk.git" source: git version: "0.5.1" diff --git a/pubspec.yaml b/pubspec.yaml index 0dfc0ca0..2871edfc 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -63,7 +63,7 @@ dependencies: polkawallet_sdk: #0.5.1 git: url: https://github.com/L3odr0id/polkawallet_sdk.git - ref: 7338432b20bbea4a4fe12d37df0fa9c5e572522a # release/0.5.1 # branch name + ref: 0d130d746954219bd165c96906f971ec1c5556a8 # release/0.5.1 # branch name ## Code gen copy_with_extension: ^5.0.3 From 0e6d8db078c4f5452f338ccb3dfe696c4e14b832 Mon Sep 17 00:00:00 2001 From: L3odr0id Date: Sat, 21 Oct 2023 16:46:20 +0300 Subject: [PATCH 4/7] WIP: cards & passwords management --- assets/translations/en.json | 4 +- lib/core/widgets/buttons/icon_button.dart | 1 + .../input/textformfield/suffix_button.dart | 15 +++--- .../input/textformfield/textformfield.dart | 8 +-- .../file_picker.dart | 2 +- .../widgets/hash_settings/trans_bytes.dart | 2 +- .../wallet_settings/node_url_textfield.dart | 2 +- .../bloc/transfer_info_cubit.dart | 34 +++++++++++- .../transfer_page/utils/dismiss_function.dart | 19 +++++++ .../widgets/add_from_card_row.dart | 9 ++-- .../widgets/basic_transfer_block.dart | 53 +++++++++++++++++-- .../widgets/basic_transfer_textfield.dart | 1 + .../widgets/from_card_basic.dart | 4 ++ .../widgets/from_card_many_to_one.dart | 8 +++ .../widgets/from_card_one_to_many.dart | 8 +++ .../widgets/froms_list_view.dart | 2 + .../transfer_page/widgets/password_hint.dart | 37 +++++++++++++ .../widgets/password_textfield.dart | 36 +++++++++++-- .../widgets/to_card_many_to_one.dart | 6 +++ .../widgets/to_card_one_to_many.dart | 6 +++ .../transfer_page/widgets/tos_list_view.dart | 2 + 21 files changed, 235 insertions(+), 24 deletions(-) create mode 100644 lib/features/wallet_screen/presentation/transfer_page/utils/dismiss_function.dart create mode 100644 lib/features/wallet_screen/presentation/transfer_page/widgets/password_hint.dart diff --git a/assets/translations/en.json b/assets/translations/en.json index f9184c25..cd03e34d 100644 --- a/assets/translations/en.json +++ b/assets/translations/en.json @@ -309,5 +309,7 @@ }, "from_select_account_title": "Select account", "add_account_from_label": "Add accout to send FROM", - "add_account_to_label": "Add accout to send TO" + "add_account_to_label": "Add accout to send TO", + "password_hint_1": "Press ", + "password_hint_2": " to copy the password of the account above" } \ No newline at end of file diff --git a/lib/core/widgets/buttons/icon_button.dart b/lib/core/widgets/buttons/icon_button.dart index 84ecb5fe..addbea38 100644 --- a/lib/core/widgets/buttons/icon_button.dart +++ b/lib/core/widgets/buttons/icon_button.dart @@ -34,6 +34,7 @@ class D3pIconButton extends StatelessWidget { @override Widget build(final BuildContext context) { return Column( + mainAxisSize: MainAxisSize.min, children: [ PlatformIconButton( icon: Icon( diff --git a/lib/core/widgets/input/textformfield/suffix_button.dart b/lib/core/widgets/input/textformfield/suffix_button.dart index 43fef53e..7dcfcd77 100644 --- a/lib/core/widgets/input/textformfield/suffix_button.dart +++ b/lib/core/widgets/input/textformfield/suffix_button.dart @@ -8,8 +8,8 @@ class _SuffixButton { required this.onSuffixButtonPressed, }); - final String? labelButton; - final String? suffixButton; + final Widget? labelButton; + final Widget? suffixButton; final void Function()? onLabelButtonPressed; final void Function()? onSuffixButtonPressed; @@ -21,11 +21,12 @@ class _SuffixButton { children: [ labelButton != null ? SizedBox( - width: 60, + height: 40, + width: 50, child: PlatformTextButton( padding: EdgeInsets.zero, onPressed: onLabelButtonPressed ?? emptyFunction, - child: Text(labelButton!), + child: labelButton, ), ) : const SizedBox(), @@ -34,14 +35,16 @@ class _SuffixButton { ), suffixButton != null ? SizedBox( - width: 60, + height: 40, + width: 50, child: PlatformTextButton( padding: EdgeInsets.zero, onPressed: onSuffixButtonPressed ?? emptyFunction, - child: Text(suffixButton!), + child: suffixButton, ), ) : const SizedBox(), + const SizedBox(width: 4), ], ) : null; diff --git a/lib/core/widgets/input/textformfield/textformfield.dart b/lib/core/widgets/input/textformfield/textformfield.dart index 093597cd..b7867dfb 100644 --- a/lib/core/widgets/input/textformfield/textformfield.dart +++ b/lib/core/widgets/input/textformfield/textformfield.dart @@ -36,6 +36,7 @@ class D3pTextFormField extends StatelessWidget { const EdgeInsets.symmetric(horizontal: 8, vertical: 12), this.focusedBorder, this.border, + this.bottomWidget, super.key, }) : controller = controller ?? TextEditingController(); @@ -46,17 +47,18 @@ class D3pTextFormField extends StatelessWidget { /// Text to display below the input field final String? bottomHelpText; + final Widget? bottomWidget; final TextEditingController controller; final bool? enabled; final String? hintText; final List? inputFormatters; final TextInputType? keyboardType; - final String? labelButton; + final Widget? labelButton; final String? labelText; final int? maxLen; final int? maxLines; - final String? suffixButton; + final Widget? suffixButton; final bool obscureText; final bool isCollapsed; final bool autofocus; @@ -127,7 +129,7 @@ class D3pTextFormField extends StatelessWidget { autovalidateMode: AutovalidateMode.onUserInteraction, ), ), - _BottomHelpText(bottomHelpText), + bottomWidget ?? _BottomHelpText(bottomHelpText), ], ); } diff --git a/lib/features/hashes_list/domain/entities/snapshot_create_from_file/file_picker.dart b/lib/features/hashes_list/domain/entities/snapshot_create_from_file/file_picker.dart index 061e9c10..b0983398 100644 --- a/lib/features/hashes_list/domain/entities/snapshot_create_from_file/file_picker.dart +++ b/lib/features/hashes_list/domain/entities/snapshot_create_from_file/file_picker.dart @@ -1,7 +1,7 @@ import 'package:file_picker/file_picker.dart'; class FilePickerShortCut { - static const allowedExtentions = ['obj', 'stl']; + static const allowedExtentions = ['obj', 'stl', 'glb', 'bin']; /// Get and validate file Future pickFile() async { diff --git a/lib/features/settings_page/presentation/widgets/hash_settings/trans_bytes.dart b/lib/features/settings_page/presentation/widgets/hash_settings/trans_bytes.dart index 95f01ffe..0ccb4f2d 100644 --- a/lib/features/settings_page/presentation/widgets/hash_settings/trans_bytes.dart +++ b/lib/features/settings_page/presentation/widgets/hash_settings/trans_bytes.dart @@ -32,7 +32,7 @@ class _State extends State { return D3pTextFormField( controller: widget.controller, labelText: 'trans_bytes_input_label'.tr(), - suffixButton: 'Clear'.tr(), + suffixButton: Text('Clear'.tr()), onSuffixButtonPressed: () => onClearPressed(context), // onChanged: (final value) => changeSettings(value ?? '', context), validator: (final input) => TransBytesInput(input ?? '').isValid, diff --git a/lib/features/settings_page/presentation/widgets/wallet_settings/node_url_textfield.dart b/lib/features/settings_page/presentation/widgets/wallet_settings/node_url_textfield.dart index e04ca763..dde8be26 100644 --- a/lib/features/settings_page/presentation/widgets/wallet_settings/node_url_textfield.dart +++ b/lib/features/settings_page/presentation/widgets/wallet_settings/node_url_textfield.dart @@ -26,7 +26,7 @@ class NodeUrlTextfield extends StatelessWidget { return D3pTextFormField( controller: textEditingController, labelText: 'node_url_label'.tr(), - labelButton: 'Reset'.tr(), + labelButton: Text('Reset'.tr()), onLabelButtonPressed: () => onResetButtonPressed(context), autofocus: true, ); diff --git a/lib/features/wallet_screen/bloc/transfer_info_cubit.dart b/lib/features/wallet_screen/bloc/transfer_info_cubit.dart index 60d4733b..d3328812 100644 --- a/lib/features/wallet_screen/bloc/transfer_info_cubit.dart +++ b/lib/features/wallet_screen/bloc/transfer_info_cubit.dart @@ -175,7 +175,7 @@ class TransferInfoCubit extends Cubit { if (dataToChange.data == acc) { return; } - print('1'); + final newFromAddresses = List.from(state.fromAddresses); final newAddressData = dataToChange.copyWith(data: acc); @@ -183,6 +183,38 @@ class TransferInfoCubit extends Cubit { emit(state.copyWith(fromAddresses: newFromAddresses)); } + + void removeFromAddress(final FromAddressData fromAddressData) { + final newFromAddresses = List.from(state.fromAddresses); + newFromAddresses.remove(fromAddressData); + + emit(state.copyWith(fromAddresses: newFromAddresses)); + } + + void removeToAddress(final ToAddressData toAddressData) { + final newToAddresses = List.from(state.toAddresses); + newToAddresses.remove(toAddressData); + + emit(state.copyWith(toAddresses: newToAddresses)); + } + + void copyPasswordIn(final FromAddressData data) { + final newFromAddresses = List.from(state.fromAddresses); + final indexOfCurrent = newFromAddresses.indexOf(data); + if (indexOfCurrent == 0 || indexOfCurrent == -1) { + return; + } + + final indexOfFocus = indexOfCurrent - 1; + final focusData = newFromAddresses[indexOfFocus]; + + final newData = data.copyWith(); + newData.passwordController.text = focusData.passwordController.text; + + newFromAddresses.replace(data, newData); + + emit(state.copyWith(fromAddresses: newFromAddresses)); + } } enum TransferScreenType { many_to_one, one_to_many } diff --git a/lib/features/wallet_screen/presentation/transfer_page/utils/dismiss_function.dart b/lib/features/wallet_screen/presentation/transfer_page/utils/dismiss_function.dart new file mode 100644 index 00000000..33feee4d --- /dev/null +++ b/lib/features/wallet_screen/presentation/transfer_page/utils/dismiss_function.dart @@ -0,0 +1,19 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:threedpass/features/wallet_screen/bloc/transfer_info_cubit.dart'; + +class DismissFunctionFabric { + final BuildContext context; + + const DismissFunctionFabric(this.context); + + void Function() buildToAddress(final ToAddressData data) { + final transferInfoCubit = BlocProvider.of(context); + return () => transferInfoCubit.removeToAddress(data); + } + + void Function() buildFromAddress(final FromAddressData data) { + final transferInfoCubit = BlocProvider.of(context); + return () => transferInfoCubit.removeFromAddress(data); + } +} diff --git a/lib/features/wallet_screen/presentation/transfer_page/widgets/add_from_card_row.dart b/lib/features/wallet_screen/presentation/transfer_page/widgets/add_from_card_row.dart index a3a2869d..808adfba 100644 --- a/lib/features/wallet_screen/presentation/transfer_page/widgets/add_from_card_row.dart +++ b/lib/features/wallet_screen/presentation/transfer_page/widgets/add_from_card_row.dart @@ -1,5 +1,6 @@ import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:threedpass/core/polkawallet/bloc/app_service_cubit.dart'; import 'package:threedpass/features/wallet_screen/bloc/transfer_info_cubit.dart'; import 'package:threedpass/features/wallet_screen/presentation/transfer_page/widgets/add_card_basic.dart'; @@ -11,14 +12,16 @@ class AddFromCardRow extends StatelessWidget { @override Widget build(final BuildContext context) { final transferInfoCubit = BlocProvider.of(context); - // print(transferInfoCubit.state.fromAddresses.length); - // print(transferInfoCubit.state.toAddresses.length); + final appServiceLoaderCubit = + BlocProvider.of(context); + final accAmount = appServiceLoaderCubit.state.keyring.allAccounts.length; return AddCardRowBasic( onPressed: () => transferInfoCubit.addFromAddress(), unlocalizedText: 'add_account_from_label', condition: (final state) => - state.screenType == TransferScreenType.many_to_one, + state.screenType == TransferScreenType.many_to_one && + state.fromAddresses.length < accAmount, ); } } diff --git a/lib/features/wallet_screen/presentation/transfer_page/widgets/basic_transfer_block.dart b/lib/features/wallet_screen/presentation/transfer_page/widgets/basic_transfer_block.dart index 35172fe9..7a806d0b 100644 --- a/lib/features/wallet_screen/presentation/transfer_page/widgets/basic_transfer_block.dart +++ b/lib/features/wallet_screen/presentation/transfer_page/widgets/basic_transfer_block.dart @@ -3,10 +3,12 @@ import 'package:flutter/material.dart'; class BasicTransferBlock extends StatelessWidget { const BasicTransferBlock({ required this.child, + this.dismiss, super.key, }); final Widget child; + final void Function()? dismiss; @override Widget build(final BuildContext context) { @@ -15,12 +17,55 @@ class BasicTransferBlock extends StatelessWidget { borderRadius: BorderRadius.all(Radius.circular(16)), ), child: Padding( - padding: const EdgeInsets.symmetric( - horizontal: 16, - vertical: 16, + padding: const EdgeInsets.only( + left: 16, + right: 16, + bottom: 16, + top: 2, + ), + child: Column( + children: [ + _DismissIcon(dismiss: dismiss), + child, + ], ), - child: child, ), ); } } + +class _DismissIcon extends StatelessWidget { + const _DismissIcon({ + required this.dismiss, + }); + final void Function()? dismiss; + + @override + Widget build(final BuildContext context) { + if (dismiss != null) { + return Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + SizedBox( + height: 24, + child: InkWell( + onTap: dismiss, + customBorder: const CircleBorder(), + child: Ink( + decoration: const BoxDecoration(shape: BoxShape.circle), + height: 24, + width: 24, + child: const Icon( + Icons.horizontal_rule_outlined, + size: 18, + ), + ), + ), + ), + ], + ); + } else { + return const SizedBox(height: 24); + } + } +} diff --git a/lib/features/wallet_screen/presentation/transfer_page/widgets/basic_transfer_textfield.dart b/lib/features/wallet_screen/presentation/transfer_page/widgets/basic_transfer_textfield.dart index bf3ec857..91366469 100644 --- a/lib/features/wallet_screen/presentation/transfer_page/widgets/basic_transfer_textfield.dart +++ b/lib/features/wallet_screen/presentation/transfer_page/widgets/basic_transfer_textfield.dart @@ -24,6 +24,7 @@ class BasicTransferTextField extends D3pTextFormField { super.suffixButton, super.validator, super.makeLabelOutside = true, + super.bottomWidget, super.border = const UnderlineInputBorder( borderSide: BorderSide.none, borderRadius: BorderRadius.all( diff --git a/lib/features/wallet_screen/presentation/transfer_page/widgets/from_card_basic.dart b/lib/features/wallet_screen/presentation/transfer_page/widgets/from_card_basic.dart index c521f7f2..48fab434 100644 --- a/lib/features/wallet_screen/presentation/transfer_page/widgets/from_card_basic.dart +++ b/lib/features/wallet_screen/presentation/transfer_page/widgets/from_card_basic.dart @@ -7,10 +7,12 @@ import 'package:threedpass/features/wallet_screen/presentation/transfer_page/wid class FromCardBasic extends StatelessWidget { const FromCardBasic({ required this.data, + required this.isFirst, super.key, }); final FromAddressData data; + final bool isFirst; @override Widget build(final BuildContext context) { @@ -22,6 +24,8 @@ class FromCardBasic extends StatelessWidget { const SizedBoxH4(), PasswordTextField( passwordController: data.passwordController, + isFirst: isFirst, + data: data, ), ], ); diff --git a/lib/features/wallet_screen/presentation/transfer_page/widgets/from_card_many_to_one.dart b/lib/features/wallet_screen/presentation/transfer_page/widgets/from_card_many_to_one.dart index 033534ba..f4499567 100644 --- a/lib/features/wallet_screen/presentation/transfer_page/widgets/from_card_many_to_one.dart +++ b/lib/features/wallet_screen/presentation/transfer_page/widgets/from_card_many_to_one.dart @@ -2,6 +2,7 @@ import 'package:flutter/material.dart'; import 'package:threedpass/core/widgets/paddings.dart'; import 'package:threedpass/features/wallet_screen/bloc/transfer_info_cubit.dart'; import 'package:threedpass/features/wallet_screen/domain/entities/transfer_meta_dto.dart'; +import 'package:threedpass/features/wallet_screen/presentation/transfer_page/utils/dismiss_function.dart'; import 'package:threedpass/features/wallet_screen/presentation/transfer_page/widgets/amount_textfield.dart'; import 'package:threedpass/features/wallet_screen/presentation/transfer_page/widgets/basic_transfer_block.dart'; import 'package:threedpass/features/wallet_screen/presentation/transfer_page/widgets/from_card_basic.dart'; @@ -11,20 +12,27 @@ class FromCardManyToOne extends StatelessWidget { required this.data, required this.sendAmountData, required this.metaInfoType, + required this.isFirst, super.key, }); final FromAddressData data; final MetaInfoType metaInfoType; final SendAmountData sendAmountData; + final bool isFirst; @override Widget build(final BuildContext context) { + final dismissFunctionFabric = DismissFunctionFabric(context); + final dismiss = + isFirst ? null : dismissFunctionFabric.buildFromAddress(data); return BasicTransferBlock( + dismiss: dismiss, child: Column( children: [ FromCardBasic( data: data, + isFirst: isFirst, ), const SizedBoxH4(), AmountTextFieldBuilder( diff --git a/lib/features/wallet_screen/presentation/transfer_page/widgets/from_card_one_to_many.dart b/lib/features/wallet_screen/presentation/transfer_page/widgets/from_card_one_to_many.dart index 2a1c4aae..2a26b919 100644 --- a/lib/features/wallet_screen/presentation/transfer_page/widgets/from_card_one_to_many.dart +++ b/lib/features/wallet_screen/presentation/transfer_page/widgets/from_card_one_to_many.dart @@ -1,21 +1,29 @@ import 'package:flutter/material.dart'; import 'package:threedpass/features/wallet_screen/bloc/transfer_info_cubit.dart'; +import 'package:threedpass/features/wallet_screen/presentation/transfer_page/utils/dismiss_function.dart'; import 'package:threedpass/features/wallet_screen/presentation/transfer_page/widgets/basic_transfer_block.dart'; import 'package:threedpass/features/wallet_screen/presentation/transfer_page/widgets/from_card_basic.dart'; class FromCardOneToMany extends StatelessWidget { const FromCardOneToMany({ required this.data, + required this.isFirst, super.key, }); final FromAddressData data; + final bool isFirst; @override Widget build(final BuildContext context) { + final dismissFunctionFabric = DismissFunctionFabric(context); + final dismiss = + isFirst ? null : dismissFunctionFabric.buildFromAddress(data); return BasicTransferBlock( + dismiss: dismiss, child: FromCardBasic( data: data, + isFirst: isFirst, ), ); } diff --git a/lib/features/wallet_screen/presentation/transfer_page/widgets/froms_list_view.dart b/lib/features/wallet_screen/presentation/transfer_page/widgets/froms_list_view.dart index b25b1ef9..7050c24e 100644 --- a/lib/features/wallet_screen/presentation/transfer_page/widgets/froms_list_view.dart +++ b/lib/features/wallet_screen/presentation/transfer_page/widgets/froms_list_view.dart @@ -27,9 +27,11 @@ class FromsListView extends StatelessWidget { data: transferInfo.fromAddresses[index], sendAmountData: transferInfo.amounts[index], metaInfoType: metaInfoType, + isFirst: index == 0, ) : FromCardOneToMany( data: transferInfo.fromAddresses[index], + isFirst: index == 0, ), ); } diff --git a/lib/features/wallet_screen/presentation/transfer_page/widgets/password_hint.dart b/lib/features/wallet_screen/presentation/transfer_page/widgets/password_hint.dart new file mode 100644 index 00000000..2e759109 --- /dev/null +++ b/lib/features/wallet_screen/presentation/transfer_page/widgets/password_hint.dart @@ -0,0 +1,37 @@ +import 'package:easy_localization/easy_localization.dart'; +import 'package:flutter/material.dart'; +import 'package:threedpass/core/theme/d3p_special_styles.dart'; + +class PasswordHint extends StatelessWidget { + const PasswordHint({super.key}); + + @override + Widget build(final BuildContext context) { + final textStyle = Theme.of(context).customTextStyles.hintStyle; + + return Padding( + padding: const EdgeInsets.only(top: 2), + child: Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + Text.rich( + TextSpan( + text: 'password_hint_1'.tr(), + children: [ + WidgetSpan( + child: Icon( + Icons.content_paste_go, + size: 14, + color: textStyle.color, + ), + ), + TextSpan(text: 'password_hint_2'.tr()), + ], + style: textStyle, + ), + ), + ], + ), + ); + } +} diff --git a/lib/features/wallet_screen/presentation/transfer_page/widgets/password_textfield.dart b/lib/features/wallet_screen/presentation/transfer_page/widgets/password_textfield.dart index 29dcc1f3..836b1dc2 100644 --- a/lib/features/wallet_screen/presentation/transfer_page/widgets/password_textfield.dart +++ b/lib/features/wallet_screen/presentation/transfer_page/widgets/password_textfield.dart @@ -1,16 +1,30 @@ import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:threedpass/core/utils/validators.dart'; +import 'package:threedpass/features/wallet_screen/bloc/transfer_info_cubit.dart'; import 'package:threedpass/features/wallet_screen/presentation/transfer_page/widgets/basic_transfer_textfield.dart'; +import 'package:threedpass/features/wallet_screen/presentation/transfer_page/widgets/password_hint.dart'; -class PasswordTextField extends StatelessWidget { +class PasswordTextField extends StatefulWidget { const PasswordTextField({ required this.passwordController, + required this.isFirst, + required this.data, final Key? key, }) : super(key: key); + final bool isFirst; + final FromAddressData data; final TextEditingController passwordController; + @override + State createState() => _State(); +} + +class _State extends State { + bool obscureText = true; + String? _passValidator(final String? v) { return v != null && Validators.checkPassword(v) ? null @@ -21,11 +35,27 @@ class PasswordTextField extends StatelessWidget { Widget build(final BuildContext context) { return BasicTransferTextField( labelText: 'enter_password_label'.tr(), - controller: passwordController, + controller: widget.passwordController, hintText: 'enter_password_hint'.tr(), validator: _passValidator, - obscureText: true, + obscureText: obscureText, maxLines: 1, + suffixButton: Icon(obscureText ? Icons.visibility : Icons.visibility_off), + onSuffixButtonPressed: obscureTextPressed, + labelButton: widget.isFirst ? null : const Icon(Icons.content_paste_go), + onLabelButtonPressed: () => onLabelButtonPressed(context), + bottomWidget: widget.isFirst ? null : const PasswordHint(), ); } + + void obscureTextPressed() { + setState(() { + obscureText = !obscureText; + }); + } + + void onLabelButtonPressed(BuildContext context) { + final transferInfo = BlocProvider.of(context); + transferInfo.copyPasswordIn(widget.data); + } } diff --git a/lib/features/wallet_screen/presentation/transfer_page/widgets/to_card_many_to_one.dart b/lib/features/wallet_screen/presentation/transfer_page/widgets/to_card_many_to_one.dart index 8e631115..82e71f1d 100644 --- a/lib/features/wallet_screen/presentation/transfer_page/widgets/to_card_many_to_one.dart +++ b/lib/features/wallet_screen/presentation/transfer_page/widgets/to_card_many_to_one.dart @@ -1,19 +1,25 @@ import 'package:flutter/material.dart'; import 'package:threedpass/features/wallet_screen/bloc/transfer_info_cubit.dart'; +import 'package:threedpass/features/wallet_screen/presentation/transfer_page/utils/dismiss_function.dart'; import 'package:threedpass/features/wallet_screen/presentation/transfer_page/widgets/basic_transfer_block.dart'; import 'package:threedpass/features/wallet_screen/presentation/transfer_page/widgets/to_card_basic.dart'; class ToCardManyToOne extends StatelessWidget { const ToCardManyToOne({ required this.data, + required this.isFirst, super.key, }); final ToAddressData data; + final bool isFirst; @override Widget build(final BuildContext context) { + final dismissFunctionFabric = DismissFunctionFabric(context); + final dismiss = isFirst ? null : dismissFunctionFabric.buildToAddress(data); return BasicTransferBlock( + dismiss: dismiss, child: ToCardBasic( data: data, ), diff --git a/lib/features/wallet_screen/presentation/transfer_page/widgets/to_card_one_to_many.dart b/lib/features/wallet_screen/presentation/transfer_page/widgets/to_card_one_to_many.dart index 65b2b37b..e08c4e46 100644 --- a/lib/features/wallet_screen/presentation/transfer_page/widgets/to_card_one_to_many.dart +++ b/lib/features/wallet_screen/presentation/transfer_page/widgets/to_card_one_to_many.dart @@ -2,6 +2,7 @@ import 'package:flutter/material.dart'; import 'package:threedpass/core/widgets/paddings.dart'; import 'package:threedpass/features/wallet_screen/bloc/transfer_info_cubit.dart'; import 'package:threedpass/features/wallet_screen/domain/entities/transfer_meta_dto.dart'; +import 'package:threedpass/features/wallet_screen/presentation/transfer_page/utils/dismiss_function.dart'; import 'package:threedpass/features/wallet_screen/presentation/transfer_page/widgets/amount_textfield.dart'; import 'package:threedpass/features/wallet_screen/presentation/transfer_page/widgets/basic_transfer_block.dart'; import 'package:threedpass/features/wallet_screen/presentation/transfer_page/widgets/to_card_basic.dart'; @@ -11,16 +12,21 @@ class ToCardOneToMany extends StatelessWidget { required this.data, required this.sendAmountData, required this.metaInfoType, + required this.isFirst, super.key, }); final ToAddressData data; final MetaInfoType metaInfoType; final SendAmountData sendAmountData; + final bool isFirst; @override Widget build(final BuildContext context) { + final dismissFunctionFabric = DismissFunctionFabric(context); + final dismiss = isFirst ? null : dismissFunctionFabric.buildToAddress(data); return BasicTransferBlock( + dismiss: dismiss, child: Column( children: [ ToCardBasic( diff --git a/lib/features/wallet_screen/presentation/transfer_page/widgets/tos_list_view.dart b/lib/features/wallet_screen/presentation/transfer_page/widgets/tos_list_view.dart index aa8513b0..177acf25 100644 --- a/lib/features/wallet_screen/presentation/transfer_page/widgets/tos_list_view.dart +++ b/lib/features/wallet_screen/presentation/transfer_page/widgets/tos_list_view.dart @@ -25,11 +25,13 @@ class ToListView extends StatelessWidget { transferInfo.screenType == TransferScreenType.many_to_one ? ToCardManyToOne( data: transferInfo.toAddresses[index], + isFirst: index == 0, ) : ToCardOneToMany( data: transferInfo.toAddresses[index], sendAmountData: transferInfo.amounts[index], metaInfoType: metaInfoType, + isFirst: index == 0, ), ); } From cc5a214f0ab1a602ec8e22c82b6589c3381e7a9e Mon Sep 17 00:00:00 2001 From: L3odr0id Date: Sun, 22 Oct 2023 20:00:04 +0300 Subject: [PATCH 5/7] WIP: Balances for transfers --- lib/core/polkawallet/utils/tx_info.dart | 192 +++++++-------- ...nfo_cubit.dart => transfer_info_bloc.dart} | 229 +++++++----------- ...cubit.g.dart => transfer_info_bloc.g.dart} | 213 ++++++++-------- .../bloc/transfer_info_bloc_event.dart | 50 ++++ .../transfer_info_bloc_fields_events.dart | 92 +++++++ .../bloc/transfer_info_bloc_state.dart | 58 +++++ .../domain/entities/multitransfer_atom.dart | 61 +++++ .../transfer_page/transfer_page.dart | 56 +---- .../transfer_page/transfer_page_wrapper.dart | 6 +- .../transfer_page/utils/dismiss_function.dart | 10 +- .../transfer_page/widgets/add_card_basic.dart | 6 +- .../widgets/add_from_card_row.dart | 6 +- .../widgets/add_to_card_row.dart | 6 +- .../transfer_page/widgets/fees_text.dart | 4 +- .../widgets/from_address_textfield.dart | 9 +- .../widgets/from_card_basic.dart | 2 +- .../widgets/from_card_many_to_one.dart | 4 +- .../widgets/from_card_one_to_many.dart | 2 +- .../widgets/froms_list_view.dart | 4 +- .../widgets/make_transfer_button.dart | 13 +- .../widgets/password_textfield.dart | 8 +- .../transfer_page/widgets/to_card_basic.dart | 2 +- .../widgets/to_card_many_to_one.dart | 2 +- .../widgets/to_card_one_to_many.dart | 4 +- .../transfer_page/widgets/tos_list_view.dart | 4 +- .../widgets/transfer_page_content.dart | 58 +++++ .../widgets/transfer_type_switch.dart | 7 +- 27 files changed, 673 insertions(+), 435 deletions(-) rename lib/features/wallet_screen/bloc/{transfer_info_cubit.dart => transfer_info_bloc.dart} (57%) rename lib/features/wallet_screen/bloc/{transfer_info_cubit.g.dart => transfer_info_bloc.g.dart} (77%) create mode 100644 lib/features/wallet_screen/bloc/transfer_info_bloc_event.dart create mode 100644 lib/features/wallet_screen/bloc/transfer_info_bloc_fields_events.dart create mode 100644 lib/features/wallet_screen/bloc/transfer_info_bloc_state.dart create mode 100644 lib/features/wallet_screen/domain/entities/multitransfer_atom.dart create mode 100644 lib/features/wallet_screen/presentation/transfer_page/widgets/transfer_page_content.dart diff --git a/lib/core/polkawallet/utils/tx_info.dart b/lib/core/polkawallet/utils/tx_info.dart index 8b5cc084..086babae 100644 --- a/lib/core/polkawallet/utils/tx_info.dart +++ b/lib/core/polkawallet/utils/tx_info.dart @@ -1,110 +1,110 @@ -import 'package:logger/logger.dart'; -import 'package:polkawallet_sdk/api/types/txInfoData.dart'; -import 'package:polkawallet_sdk/plugin/store/balances.dart'; -import 'package:polkawallet_sdk/storage/types/keyPairData.dart'; -import 'package:threedpass/core/polkawallet/utils/balance_utils.dart'; -import 'package:threedpass/core/polkawallet/utils/transfer_type.dart'; -import 'package:threedpass/setup.dart'; +// import 'package:logger/logger.dart'; +// import 'package:polkawallet_sdk/api/types/txInfoData.dart'; +// import 'package:polkawallet_sdk/plugin/store/balances.dart'; +// import 'package:polkawallet_sdk/storage/types/keyPairData.dart'; +// import 'package:threedpass/core/polkawallet/utils/balance_utils.dart'; +// import 'package:threedpass/core/polkawallet/utils/transfer_type.dart'; +// import 'package:threedpass/setup.dart'; -abstract class TransferTxInfoI { - final KeyPairData senderData; - final int decimals; +// abstract class TransferTxInfoI { +// final KeyPairData senderData; +// final int decimals; - const TransferTxInfoI({ - required this.decimals, - required this.senderData, - }); +// const TransferTxInfoI({ +// required this.decimals, +// required this.senderData, +// }); - TxInfoData txInfo( - final TransactionOption transferType, - ); - List params(final String? amount, final String toAddress); -} +// TxInfoData txInfo( +// final TransactionOption transferType, +// ); +// List params(final String? amount, final String toAddress); +// } -class AssetsTransferTx extends TransferTxInfoI { - final TokenBalanceData tokenBalanceData; - const AssetsTransferTx({ - required super.decimals, - required super.senderData, - required this.tokenBalanceData, - }); +// class AssetsTransferTx extends TransferTxInfoI { +// final TokenBalanceData tokenBalanceData; +// const AssetsTransferTx({ +// required super.decimals, +// required super.senderData, +// required this.tokenBalanceData, +// }); - @override - TxInfoData txInfo( - final TransactionOption transferType, - ) => - TxInfoData( - 'assets', - TransferTypeValue(transferType).toString(), - TxSenderData(senderData.address, senderData.pubKey), - ); +// @override +// TxInfoData txInfo( +// final TransactionOption transferType, +// ) => +// TxInfoData( +// 'assets', +// TransferTypeValue(transferType).toString(), +// TxSenderData(senderData.address, senderData.pubKey), +// ); - @override - List params( - final String? amount, - final String toAddress, - ) { - // https://polkadot.js.org/docs/substrate/extrinsics/#transferid-compactu32-target-multiaddress-amount-compactu128 +// @override +// List params( +// final String? amount, +// final String toAddress, +// ) { +// // https://polkadot.js.org/docs/substrate/extrinsics/#transferid-compactu32-target-multiaddress-amount-compactu128 - if (tokenBalanceData.decimals == null) { - getIt().w( - 'DANGER! tokenBalanceData.decimals is null when get params for AssetsTransferTx.', - ); - } +// if (tokenBalanceData.decimals == null) { +// getIt().w( +// 'DANGER! tokenBalanceData.decimals is null when get params for AssetsTransferTx.', +// ); +// } - final realAmount = BalanceUtils.tokenInt( - amount, - tokenBalanceData.decimals ?? decimals, - ); +// final realAmount = BalanceUtils.tokenInt( +// amount, +// tokenBalanceData.decimals ?? decimals, +// ); - if (tokenBalanceData.id == null) { - throw Exception('TokenBalanceData.id is null'); - } +// if (tokenBalanceData.id == null) { +// throw Exception('TokenBalanceData.id is null'); +// } - return [ - tokenBalanceData.id!, - // params.to - toAddress, - // params.amount - realAmount.toString(), - ]; - } -} +// return [ +// tokenBalanceData.id!, +// // params.to +// toAddress, +// // params.amount +// realAmount.toString(), +// ]; +// } +// } -class CoinsTransferTx extends TransferTxInfoI { - const CoinsTransferTx({ - required super.decimals, - required super.senderData, - }); +// class CoinsTransferTx extends TransferTxInfoI { +// const CoinsTransferTx({ +// required super.decimals, +// required super.senderData, +// }); - @override - TxInfoData txInfo( - final TransactionOption transferType, - ) => - TxInfoData( - 'balances', - TransferTypeValue(transferType).toString(), - TxSenderData( - senderData.address, - senderData.pubKey, - ), - ); +// @override +// TxInfoData txInfo( +// final TransactionOption transferType, +// ) => +// TxInfoData( +// 'balances', +// TransferTypeValue(transferType).toString(), +// TxSenderData( +// senderData.address, +// senderData.pubKey, +// ), +// ); - @override - List params( - final String? amount, - final String toAddress, - ) { - final realAmount = BalanceUtils.tokenInt( - amount, - decimals, - ); +// @override +// List params( +// final String? amount, +// final String toAddress, +// ) { +// final realAmount = BalanceUtils.tokenInt( +// amount, +// decimals, +// ); - return [ - // params.to - toAddress, - // params.amount - realAmount.toString(), - ]; - } -} +// return [ +// // params.to +// toAddress, +// // params.amount +// realAmount.toString(), +// ]; +// } +// } diff --git a/lib/features/wallet_screen/bloc/transfer_info_cubit.dart b/lib/features/wallet_screen/bloc/transfer_info_bloc.dart similarity index 57% rename from lib/features/wallet_screen/bloc/transfer_info_cubit.dart rename to lib/features/wallet_screen/bloc/transfer_info_bloc.dart index d3328812..8a227014 100644 --- a/lib/features/wallet_screen/bloc/transfer_info_cubit.dart +++ b/lib/features/wallet_screen/bloc/transfer_info_bloc.dart @@ -1,3 +1,5 @@ +import 'dart:async'; + import 'package:copy_with_extension/copy_with_extension.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; @@ -5,17 +7,23 @@ import 'package:polkawallet_sdk/api/types/txInfoData.dart'; import 'package:polkawallet_sdk/storage/types/keyPairData.dart'; import 'package:super_core/super_core.dart'; import 'package:threedpass/core/polkawallet/app_service.dart'; +import 'package:threedpass/core/polkawallet/utils/balance_utils.dart'; +import 'package:threedpass/core/polkawallet/utils/network_state_data_extension.dart'; import 'package:threedpass/core/polkawallet/utils/transfer_type.dart'; import 'package:threedpass/features/wallet_screen/domain/entities/transfer_meta_dto.dart'; -part 'transfer_info_cubit.g.dart'; +part 'transfer_info_bloc.g.dart'; +part 'transfer_info_bloc_event.dart'; +part 'transfer_info_bloc_state.dart'; +part 'transfer_info_bloc_fields_events.dart'; -class TransferInfoCubit extends Cubit { - TransferInfoCubit({ +class TransferInfoBloc + extends Bloc { + TransferInfoBloc({ required this.metaDTO, required this.appService, }) : super( - TransferInfo( + TransferInfoBlocState( fromAddresses: [initialFrom(appService)], toAddresses: [ ToAddressData( @@ -23,14 +31,38 @@ class TransferInfoCubit extends Cubit { ), ], fees: null, - type: TransferTypeValue.defaultType, + transactionOption: TransferTypeValue.defaultType, amounts: [ SendAmountData( amountController: TextEditingController(), + balance: initialBalance(appService), ), ], ), - ); + ) { + final initialAddress = initialFrom(appService).data!.address!; + final balance = initialBalance(appService); + + balanceCache = { + initialAddress: balance, + }; + + on(_updateTransferType); + on(_addFromAddress); + on(_addToAddress); + on(_changeChosenAccount); + on(_setBalanceAmount); + on(_removeFromAddress); + on(_removeToAddress); + on(_copyPassword); + } + static double initialBalance(final AppService appService) { + final rawAvaliable = + appService.chosenAccountBalance.value.availableBalance as String; + final decimals = appService.networkStateData.safeDecimals; + final res = BalanceUtils.balanceToDouble(rawAvaliable, decimals); + return res; + } static FromAddressData initialFrom(final AppService appService) { final account = appService.keyring.current; @@ -47,6 +79,8 @@ class TransferInfoCubit extends Cubit { final TransferMetaDTO metaDTO; final AppService appService; + late final Map balanceCache; + Future init() async { // final txInfo = metaDTO.getTxInfo(state.type); // final params = metaDTO.getParams( @@ -84,10 +118,7 @@ class TransferInfoCubit extends Cubit { } Future sendTransfer({ - required final String amount, - required final String toAddress, required final BuildContext context, - required final String password, required final GlobalKey formKey, }) async { // final txInfo = metaDTO.getTxInfo(state.type); @@ -117,61 +148,22 @@ class TransferInfoCubit extends Cubit { // ).sendFunds(); } - void updateTransferType(final TransactionOption type) { - emit(state.copyWith(type: type)); - } - - void addFromAddress() { - final newFromAddresses = List.from(state.fromAddresses); - newFromAddresses.add( - FromAddressData( - data: null, - passwordController: TextEditingController(), - ), - ); - - final newAmountsList = List.from(state.amounts); - newAmountsList.add( - SendAmountData( - amountController: TextEditingController(), - ), - ); - - emit( - state.copyWith( - fromAddresses: newFromAddresses, - amounts: newAmountsList, - ), - ); - } - - void addToAddress() { - final newToAddresses = List.from(state.toAddresses); - newToAddresses.add( - ToAddressData( - toAddressController: TextEditingController(), - ), - ); - - final newAmountsList = List.from(state.amounts); - newAmountsList.add( - SendAmountData( - amountController: TextEditingController(), - ), - ); - - emit( - state.copyWith( - toAddresses: newToAddresses, - amounts: newAmountsList, - ), - ); + void _updateTransferType( + final UpdateTransferTypeEvent event, + final Emitter emit, + ) { + // emit(state.copyWith(type: type)); + final newState = state.copyWith(transactionOption: event.value); + emit(newState); } - void changeChosenAccount( - final FromAddressData dataToChange, - final KeyPairData? acc, + void _changeChosenAccount( + final ChangeChosenAccountEvent event, + final Emitter emit, ) { + final dataToChange = event.dataToChange; + final acc = event.acc; + if (dataToChange.data == acc) { return; } @@ -182,23 +174,15 @@ class TransferInfoCubit extends Cubit { newFromAddresses.replace(dataToChange, newAddressData); emit(state.copyWith(fromAddresses: newFromAddresses)); - } - void removeFromAddress(final FromAddressData fromAddressData) { - final newFromAddresses = List.from(state.fromAddresses); - newFromAddresses.remove(fromAddressData); - - emit(state.copyWith(fromAddresses: newFromAddresses)); + add(SetBalanceAmountEvent(newAddressData)); } - void removeToAddress(final ToAddressData toAddressData) { - final newToAddresses = List.from(state.toAddresses); - newToAddresses.remove(toAddressData); - - emit(state.copyWith(toAddresses: newToAddresses)); - } - - void copyPasswordIn(final FromAddressData data) { + void _copyPassword( + final CopyPasswordEvent event, + final Emitter emit, + ) { + final data = event.fromAddressData; final newFromAddresses = List.from(state.fromAddresses); final indexOfCurrent = newFromAddresses.indexOf(data); if (indexOfCurrent == 0 || indexOfCurrent == -1) { @@ -215,74 +199,43 @@ class TransferInfoCubit extends Cubit { emit(state.copyWith(fromAddresses: newFromAddresses)); } -} -enum TransferScreenType { many_to_one, one_to_many } - -@CopyWith() -class TransferInfo { - // Max avaliable balance in wallet in human-readable double format - // final double balance; - final TxFeeEstimateResult? fees; - final TransactionOption type; - final List fromAddresses; - final List toAddresses; - final List amounts; - - const TransferInfo({ - required this.fromAddresses, - required this.toAddresses, - required this.fees, - required this.type, - required this.amounts, - }); - - TransferScreenType get screenType => - fromAddresses.length >= toAddresses.length - ? TransferScreenType.many_to_one - : TransferScreenType.one_to_many; -} + FutureOr getBalance(final String address) async { + if (balanceCache.containsKey(address)) { + return Future.value(balanceCache[address]!); + } else { + final balanceData = + await appService.plugin.sdk.api.account.queryBalance(address); + final decimals = appService.networkStateData.safeDecimals; + final rawAvaliableBalance = balanceData!.availableBalance as String; + final balance = + BalanceUtils.balanceToDouble(rawAvaliableBalance, decimals); + balanceCache[address] = balance; + return balance; + } + } -// @CopyWith() -// class AddressData { -// const AddressData({ -// required this.data, -// required this.addressController, -// required this.passwordController, -// }); - -// final KeyPairData? data; -// final TextEditingController addressController; -// final TextEditingController passwordController; -// } - -@CopyWith() -class FromAddressData { - const FromAddressData({ - required this.data, - required this.passwordController, - }); - - final KeyPairData? data; - final TextEditingController passwordController; -} + Future _setBalanceAmount( + final SetBalanceAmountEvent event, + final Emitter emit, + ) async { + final accAddress = event.fromAddressData.data?.address; -@CopyWith() -class ToAddressData { - const ToAddressData({ - required this.toAddressController, - }); + if (accAddress == null) { + return; + } - final TextEditingController toAddressController; -} + final balance = await getBalance(accAddress); -@CopyWith() -class SendAmountData { - const SendAmountData({ - required this.amountController, - }); + // Some racing is possible + final newAmountsList = List.from(state.amounts); + final newFromAddresses = List.from(state.fromAddresses); + final indexOfCurrent = newFromAddresses.indexOf(event.fromAddressData); - final TextEditingController amountController; + final oldAmount = newAmountsList[indexOfCurrent]; + final newAmount = oldAmount.copyWith(balance: balance); + newAmountsList.replace(oldAmount, newAmount); - // double? get amount => double.tryParse(amountController.text); + emit(state.copyWith(amounts: newAmountsList)); + } } diff --git a/lib/features/wallet_screen/bloc/transfer_info_cubit.g.dart b/lib/features/wallet_screen/bloc/transfer_info_bloc.g.dart similarity index 77% rename from lib/features/wallet_screen/bloc/transfer_info_cubit.g.dart rename to lib/features/wallet_screen/bloc/transfer_info_bloc.g.dart index 3d277be9..94f87812 100644 --- a/lib/features/wallet_screen/bloc/transfer_info_cubit.g.dart +++ b/lib/features/wallet_screen/bloc/transfer_info_bloc.g.dart @@ -1,108 +1,11 @@ // GENERATED CODE - DO NOT MODIFY BY HAND -part of 'transfer_info_cubit.dart'; +part of 'transfer_info_bloc.dart'; // ************************************************************************** // CopyWithGenerator // ************************************************************************** -abstract class _$TransferInfoCWProxy { - TransferInfo fromAddresses(List fromAddresses); - - TransferInfo toAddresses(List toAddresses); - - TransferInfo fees(TxFeeEstimateResult? fees); - - TransferInfo type(TransactionOption type); - - TransferInfo amounts(List amounts); - - /// This function **does support** nullification of nullable fields. All `null` values passed to `non-nullable` fields will be ignored. You can also use `TransferInfo(...).copyWith.fieldName(...)` to override fields one at a time with nullification support. - /// - /// Usage - /// ```dart - /// TransferInfo(...).copyWith(id: 12, name: "My name") - /// ```` - TransferInfo call({ - List? fromAddresses, - List? toAddresses, - TxFeeEstimateResult? fees, - TransactionOption? type, - List? amounts, - }); -} - -/// Proxy class for `copyWith` functionality. This is a callable class and can be used as follows: `instanceOfTransferInfo.copyWith(...)`. Additionally contains functions for specific fields e.g. `instanceOfTransferInfo.copyWith.fieldName(...)` -class _$TransferInfoCWProxyImpl implements _$TransferInfoCWProxy { - const _$TransferInfoCWProxyImpl(this._value); - - final TransferInfo _value; - - @override - TransferInfo fromAddresses(List fromAddresses) => - this(fromAddresses: fromAddresses); - - @override - TransferInfo toAddresses(List toAddresses) => - this(toAddresses: toAddresses); - - @override - TransferInfo fees(TxFeeEstimateResult? fees) => this(fees: fees); - - @override - TransferInfo type(TransactionOption type) => this(type: type); - - @override - TransferInfo amounts(List amounts) => this(amounts: amounts); - - @override - - /// This function **does support** nullification of nullable fields. All `null` values passed to `non-nullable` fields will be ignored. You can also use `TransferInfo(...).copyWith.fieldName(...)` to override fields one at a time with nullification support. - /// - /// Usage - /// ```dart - /// TransferInfo(...).copyWith(id: 12, name: "My name") - /// ```` - TransferInfo call({ - Object? fromAddresses = const $CopyWithPlaceholder(), - Object? toAddresses = const $CopyWithPlaceholder(), - Object? fees = const $CopyWithPlaceholder(), - Object? type = const $CopyWithPlaceholder(), - Object? amounts = const $CopyWithPlaceholder(), - }) { - return TransferInfo( - fromAddresses: - fromAddresses == const $CopyWithPlaceholder() || fromAddresses == null - ? _value.fromAddresses - // ignore: cast_nullable_to_non_nullable - : fromAddresses as List, - toAddresses: - toAddresses == const $CopyWithPlaceholder() || toAddresses == null - ? _value.toAddresses - // ignore: cast_nullable_to_non_nullable - : toAddresses as List, - fees: fees == const $CopyWithPlaceholder() - ? _value.fees - // ignore: cast_nullable_to_non_nullable - : fees as TxFeeEstimateResult?, - type: type == const $CopyWithPlaceholder() || type == null - ? _value.type - // ignore: cast_nullable_to_non_nullable - : type as TransactionOption, - amounts: amounts == const $CopyWithPlaceholder() || amounts == null - ? _value.amounts - // ignore: cast_nullable_to_non_nullable - : amounts as List, - ); - } -} - -extension $TransferInfoCopyWith on TransferInfo { - /// Returns a callable class that can be used as follows: `instanceOfTransferInfo.copyWith(...)` or like so:`instanceOfTransferInfo.copyWith.fieldName(...)`. - // ignore: library_private_types_in_public_api - _$TransferInfoCWProxy get copyWith => _$TransferInfoCWProxyImpl(this); -} - abstract class _$FromAddressDataCWProxy { FromAddressData data(KeyPairData? data); @@ -222,6 +125,8 @@ extension $ToAddressDataCopyWith on ToAddressData { abstract class _$SendAmountDataCWProxy { SendAmountData amountController(TextEditingController amountController); + SendAmountData balance(double? balance); + /// This function **does support** nullification of nullable fields. All `null` values passed to `non-nullable` fields will be ignored. You can also use `SendAmountData(...).copyWith.fieldName(...)` to override fields one at a time with nullification support. /// /// Usage @@ -230,6 +135,7 @@ abstract class _$SendAmountDataCWProxy { /// ```` SendAmountData call({ TextEditingController? amountController, + double? balance, }); } @@ -243,6 +149,9 @@ class _$SendAmountDataCWProxyImpl implements _$SendAmountDataCWProxy { SendAmountData amountController(TextEditingController amountController) => this(amountController: amountController); + @override + SendAmountData balance(double? balance) => this(balance: balance); + @override /// This function **does support** nullification of nullable fields. All `null` values passed to `non-nullable` fields will be ignored. You can also use `SendAmountData(...).copyWith.fieldName(...)` to override fields one at a time with nullification support. @@ -253,6 +162,7 @@ class _$SendAmountDataCWProxyImpl implements _$SendAmountDataCWProxy { /// ```` SendAmountData call({ Object? amountController = const $CopyWithPlaceholder(), + Object? balance = const $CopyWithPlaceholder(), }) { return SendAmountData( amountController: amountController == const $CopyWithPlaceholder() || @@ -260,6 +170,10 @@ class _$SendAmountDataCWProxyImpl implements _$SendAmountDataCWProxy { ? _value.amountController // ignore: cast_nullable_to_non_nullable : amountController as TextEditingController, + balance: balance == const $CopyWithPlaceholder() + ? _value.balance + // ignore: cast_nullable_to_non_nullable + : balance as double?, ); } } @@ -269,3 +183,106 @@ extension $SendAmountDataCopyWith on SendAmountData { // ignore: library_private_types_in_public_api _$SendAmountDataCWProxy get copyWith => _$SendAmountDataCWProxyImpl(this); } + +abstract class _$TransferInfoBlocStateCWProxy { + TransferInfoBlocState fromAddresses(List fromAddresses); + + TransferInfoBlocState toAddresses(List toAddresses); + + TransferInfoBlocState fees(TxFeeEstimateResult? fees); + + TransferInfoBlocState transactionOption(TransactionOption transactionOption); + + TransferInfoBlocState amounts(List amounts); + + /// This function **does support** nullification of nullable fields. All `null` values passed to `non-nullable` fields will be ignored. You can also use `TransferInfoBlocState(...).copyWith.fieldName(...)` to override fields one at a time with nullification support. + /// + /// Usage + /// ```dart + /// TransferInfoBlocState(...).copyWith(id: 12, name: "My name") + /// ```` + TransferInfoBlocState call({ + List? fromAddresses, + List? toAddresses, + TxFeeEstimateResult? fees, + TransactionOption? transactionOption, + List? amounts, + }); +} + +/// Proxy class for `copyWith` functionality. This is a callable class and can be used as follows: `instanceOfTransferInfoBlocState.copyWith(...)`. Additionally contains functions for specific fields e.g. `instanceOfTransferInfoBlocState.copyWith.fieldName(...)` +class _$TransferInfoBlocStateCWProxyImpl + implements _$TransferInfoBlocStateCWProxy { + const _$TransferInfoBlocStateCWProxyImpl(this._value); + + final TransferInfoBlocState _value; + + @override + TransferInfoBlocState fromAddresses(List fromAddresses) => + this(fromAddresses: fromAddresses); + + @override + TransferInfoBlocState toAddresses(List toAddresses) => + this(toAddresses: toAddresses); + + @override + TransferInfoBlocState fees(TxFeeEstimateResult? fees) => this(fees: fees); + + @override + TransferInfoBlocState transactionOption( + TransactionOption transactionOption) => + this(transactionOption: transactionOption); + + @override + TransferInfoBlocState amounts(List amounts) => + this(amounts: amounts); + + @override + + /// This function **does support** nullification of nullable fields. All `null` values passed to `non-nullable` fields will be ignored. You can also use `TransferInfoBlocState(...).copyWith.fieldName(...)` to override fields one at a time with nullification support. + /// + /// Usage + /// ```dart + /// TransferInfoBlocState(...).copyWith(id: 12, name: "My name") + /// ```` + TransferInfoBlocState call({ + Object? fromAddresses = const $CopyWithPlaceholder(), + Object? toAddresses = const $CopyWithPlaceholder(), + Object? fees = const $CopyWithPlaceholder(), + Object? transactionOption = const $CopyWithPlaceholder(), + Object? amounts = const $CopyWithPlaceholder(), + }) { + return TransferInfoBlocState( + fromAddresses: + fromAddresses == const $CopyWithPlaceholder() || fromAddresses == null + ? _value.fromAddresses + // ignore: cast_nullable_to_non_nullable + : fromAddresses as List, + toAddresses: + toAddresses == const $CopyWithPlaceholder() || toAddresses == null + ? _value.toAddresses + // ignore: cast_nullable_to_non_nullable + : toAddresses as List, + fees: fees == const $CopyWithPlaceholder() + ? _value.fees + // ignore: cast_nullable_to_non_nullable + : fees as TxFeeEstimateResult?, + transactionOption: transactionOption == const $CopyWithPlaceholder() || + transactionOption == null + ? _value.transactionOption + // ignore: cast_nullable_to_non_nullable + : transactionOption as TransactionOption, + amounts: amounts == const $CopyWithPlaceholder() || amounts == null + ? _value.amounts + // ignore: cast_nullable_to_non_nullable + : amounts as List, + ); + } +} + +extension $TransferInfoBlocStateCopyWith on TransferInfoBlocState { + /// Returns a callable class that can be used as follows: `instanceOfTransferInfoBlocState.copyWith(...)` or like so:`instanceOfTransferInfoBlocState.copyWith.fieldName(...)`. + // ignore: library_private_types_in_public_api + _$TransferInfoBlocStateCWProxy get copyWith => + _$TransferInfoBlocStateCWProxyImpl(this); +} diff --git a/lib/features/wallet_screen/bloc/transfer_info_bloc_event.dart b/lib/features/wallet_screen/bloc/transfer_info_bloc_event.dart new file mode 100644 index 00000000..ce26fa9b --- /dev/null +++ b/lib/features/wallet_screen/bloc/transfer_info_bloc_event.dart @@ -0,0 +1,50 @@ +part of 'transfer_info_bloc.dart'; + +abstract class TransferInfoBlocEvent { + const TransferInfoBlocEvent(); +} + +class UpdateTransferTypeEvent extends TransferInfoBlocEvent { + final TransactionOption value; + + const UpdateTransferTypeEvent(this.value); +} + +class AddFromAddressEvent extends TransferInfoBlocEvent { + const AddFromAddressEvent(); +} + +class RemoveFromAddressEvent extends TransferInfoBlocEvent { + final FromAddressData fromAddressData; + const RemoveFromAddressEvent(this.fromAddressData); +} + +class AddToAddressEvent extends TransferInfoBlocEvent { + const AddToAddressEvent(); +} + +class RemoveToAddressEvent extends TransferInfoBlocEvent { + final ToAddressData toAddressData; + const RemoveToAddressEvent(this.toAddressData); +} + +class ChangeChosenAccountEvent extends TransferInfoBlocEvent { + final FromAddressData dataToChange; + final KeyPairData? acc; + + const ChangeChosenAccountEvent({ + required this.acc, + required this.dataToChange, + }); +} + +class SetBalanceAmountEvent extends TransferInfoBlocEvent { + final FromAddressData fromAddressData; + + const SetBalanceAmountEvent(this.fromAddressData); +} + +class CopyPasswordEvent extends TransferInfoBlocEvent { + final FromAddressData fromAddressData; + const CopyPasswordEvent(this.fromAddressData); +} diff --git a/lib/features/wallet_screen/bloc/transfer_info_bloc_fields_events.dart b/lib/features/wallet_screen/bloc/transfer_info_bloc_fields_events.dart new file mode 100644 index 00000000..edef04a0 --- /dev/null +++ b/lib/features/wallet_screen/bloc/transfer_info_bloc_fields_events.dart @@ -0,0 +1,92 @@ +part of 'transfer_info_bloc.dart'; + +extension FieldEvents on TransferInfoBloc { + void _addFromAddress( + final AddFromAddressEvent event, + final Emitter emit, + ) { + final newFromAddresses = List.from(state.fromAddresses); + newFromAddresses.add( + FromAddressData( + data: null, + passwordController: TextEditingController(), + ), + ); + + final newAmountsList = List.from(state.amounts); + newAmountsList.add( + SendAmountData( + amountController: TextEditingController(), + balance: null, + ), + ); + + emit( + state.copyWith( + fromAddresses: newFromAddresses, + amounts: newAmountsList, + ), + ); + } + + void _addToAddress( + final AddToAddressEvent event, + final Emitter emit, + ) { + final newToAddresses = List.from(state.toAddresses); + newToAddresses.add( + ToAddressData( + toAddressController: TextEditingController(), + ), + ); + + final firstAccAddress = state.fromAddresses.first.data!.address; + final firstAccBalance = balanceCache[firstAccAddress]; + + final newAmountsList = []; + for (final i in state.amounts) { + newAmountsList.add(i.copyWith(balance: firstAccBalance)); + } + newAmountsList.add( + SendAmountData( + amountController: TextEditingController(), + balance: firstAccBalance, + ), + ); + + emit( + state.copyWith( + toAddresses: newToAddresses, + amounts: newAmountsList, + ), + ); + } + + void _removeFromAddress( + final RemoveFromAddressEvent event, + final Emitter emit, + ) { + final newFromAddresses = List.from(state.fromAddresses); + final index = newFromAddresses.indexOf(event.fromAddressData); + newFromAddresses.remove(event.fromAddressData); + + final newAmounts = List.from(state.amounts); + newAmounts.removeAt(index); + + emit(state.copyWith(fromAddresses: newFromAddresses, amounts: newAmounts)); + } + + void _removeToAddress( + final RemoveToAddressEvent event, + final Emitter emit, + ) { + final newToAddresses = List.from(state.toAddresses); + final index = newToAddresses.indexOf(event.toAddressData); + newToAddresses.remove(event.toAddressData); + + final newAmounts = List.from(state.amounts); + newAmounts.removeAt(index); + + emit(state.copyWith(toAddresses: newToAddresses, amounts: newAmounts)); + } +} diff --git a/lib/features/wallet_screen/bloc/transfer_info_bloc_state.dart b/lib/features/wallet_screen/bloc/transfer_info_bloc_state.dart new file mode 100644 index 00000000..ff14827a --- /dev/null +++ b/lib/features/wallet_screen/bloc/transfer_info_bloc_state.dart @@ -0,0 +1,58 @@ +part of 'transfer_info_bloc.dart'; + +@CopyWith() +class TransferInfoBlocState { + // Max avaliable balance in wallet in human-readable double format + // final double balance; + final TxFeeEstimateResult? fees; + final TransactionOption transactionOption; + final List fromAddresses; + final List toAddresses; + final List amounts; + + const TransferInfoBlocState({ + required this.fromAddresses, + required this.toAddresses, + required this.fees, + required this.transactionOption, + required this.amounts, + }); + + TransferScreenType get screenType => + fromAddresses.length >= toAddresses.length + ? TransferScreenType.many_to_one + : TransferScreenType.one_to_many; +} + +enum TransferScreenType { many_to_one, one_to_many } + +@CopyWith() +class FromAddressData { + const FromAddressData({ + required this.data, + required this.passwordController, + }); + + final KeyPairData? data; + final TextEditingController passwordController; +} + +@CopyWith() +class ToAddressData { + const ToAddressData({ + required this.toAddressController, + }); + + final TextEditingController toAddressController; +} + +@CopyWith() +class SendAmountData { + const SendAmountData({ + required this.amountController, + required this.balance, + }); + + final TextEditingController amountController; + final double? balance; +} diff --git a/lib/features/wallet_screen/domain/entities/multitransfer_atom.dart b/lib/features/wallet_screen/domain/entities/multitransfer_atom.dart new file mode 100644 index 00000000..4eb5a9fb --- /dev/null +++ b/lib/features/wallet_screen/domain/entities/multitransfer_atom.dart @@ -0,0 +1,61 @@ +import 'package:polkawallet_sdk/api/types/txInfoData.dart'; +import 'package:polkawallet_sdk/storage/types/keyPairData.dart'; +import 'package:threedpass/core/polkawallet/utils/balance_utils.dart'; +import 'package:threedpass/core/polkawallet/utils/transfer_type.dart'; + +abstract class TransferTxInfoI { + final KeyPairData senderData; + final int decimals; + + const TransferTxInfoI({ + required this.decimals, + required this.senderData, + }); + + TxInfoData txInfo( + final TransactionOption transferType, + ); + List params(final String? amount, final String toAddress); +} + +class MultitransferAtomCoins extends TransferTxInfoI { + // txinfo + final String senderAddress; + final String senderPubKey; + final TransactionOption transferType; + final String module = 'balances'; + final int decimals; + + // params + final String toAddress; + final double amount; + + TxInfoData txInfo( + final TransactionOption transferType, + ) => + TxInfoData( + 'balances', + TransferTypeValue(transferType).toString(), + TxSenderData( + senderAddress, + senderPubKey, + ), + ); + + List params( + final String? amount, + final String toAddress, + ) { + final realAmount = BalanceUtils.tokenInt( + amount, + decimals, + ); + + return [ + // params.to + toAddress, + // params.amount + realAmount.toString(), + ]; + } +} diff --git a/lib/features/wallet_screen/presentation/transfer_page/transfer_page.dart b/lib/features/wallet_screen/presentation/transfer_page/transfer_page.dart index 41d57514..ae622946 100644 --- a/lib/features/wallet_screen/presentation/transfer_page/transfer_page.dart +++ b/lib/features/wallet_screen/presentation/transfer_page/transfer_page.dart @@ -6,13 +6,8 @@ import 'package:threedpass/core/polkawallet/app_service.dart'; import 'package:threedpass/core/polkawallet/bloc/app_service_cubit.dart'; import 'package:threedpass/core/widgets/buttons/elevated_button.dart'; import 'package:threedpass/core/widgets/d3p_scaffold.dart'; -import 'package:threedpass/core/widgets/paddings.dart'; -import 'package:threedpass/features/wallet_screen/bloc/transfer_info_cubit.dart'; -import 'package:threedpass/features/wallet_screen/presentation/transfer_page/widgets/add_from_card_row.dart'; -import 'package:threedpass/features/wallet_screen/presentation/transfer_page/widgets/add_to_card_row.dart'; -import 'package:threedpass/features/wallet_screen/presentation/transfer_page/widgets/froms_list_view.dart'; -import 'package:threedpass/features/wallet_screen/presentation/transfer_page/widgets/tos_list_view.dart'; -import 'package:threedpass/features/wallet_screen/presentation/transfer_page/widgets/transfer_type_switch.dart'; +import 'package:threedpass/features/wallet_screen/bloc/transfer_info_bloc.dart'; +import 'package:threedpass/features/wallet_screen/presentation/transfer_page/widgets/transfer_page_content.dart'; part './widgets/make_transfer_button.dart'; @@ -27,7 +22,7 @@ class TransferPage extends StatelessWidget { @override Widget build(final BuildContext context) { final appService = BlocProvider.of(context).state; - final transferInfo = BlocProvider.of(context); + final transferInfo = BlocProvider.of(context); // appService.keyring. return D3pScaffold( appbarTitle: 'transfer_page_title'.tr() + ' ' + transferInfo.metaDTO.name, @@ -39,45 +34,9 @@ class TransferPage extends StatelessWidget { padding: const EdgeInsets.symmetric(horizontal: 8), child: Form( key: _formKey, - child: BlocBuilder( - builder: (final context, final state) { - return Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - const SizedBoxH8(), - - FromsListView( - transferInfo: state, - metaInfoType: transferInfo.metaDTO.type, - ), - - const AddFromCardRow(), - - const Align( - alignment: Alignment.center, - child: Icon( - Icons.arrow_downward_outlined, - size: 30, - ), - ), - - // const SizedBoxH24(), - ToListView( - transferInfo: state, - metaInfoType: transferInfo.metaDTO.type, - ), - - const AddToCardRow(), - - // const SizedBoxH16(), - - const TransferTypeSwitch(), - // const SizedBox(height: 24), - // const FeesText(), - const SizedBox(height: 72), - ], - ); - }, + child: BlocBuilder( + builder: (final context, final state) => + TransferPageAddressesList(state: state), ), ), ), @@ -87,9 +46,6 @@ class TransferPage extends StatelessWidget { child: Padding( padding: const EdgeInsets.symmetric(vertical: 16, horizontal: 16), child: _MakeTransferButton( - toAddressController: TextEditingController(), - amountController: TextEditingController(), - passwordController: TextEditingController(), formKey: _formKey, appService: appService, ), diff --git a/lib/features/wallet_screen/presentation/transfer_page/transfer_page_wrapper.dart b/lib/features/wallet_screen/presentation/transfer_page/transfer_page_wrapper.dart index 99fb0706..e8c35f91 100644 --- a/lib/features/wallet_screen/presentation/transfer_page/transfer_page_wrapper.dart +++ b/lib/features/wallet_screen/presentation/transfer_page/transfer_page_wrapper.dart @@ -3,7 +3,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:threedpass/core/polkawallet/bloc/app_service_cubit.dart'; import 'package:threedpass/features/preview_page/bloc/outer_context_cubit.dart'; -import 'package:threedpass/features/wallet_screen/bloc/transfer_info_cubit.dart'; +import 'package:threedpass/features/wallet_screen/bloc/transfer_info_bloc.dart'; import 'package:threedpass/features/wallet_screen/domain/entities/transfer_meta_dto.dart'; @RoutePage() @@ -21,9 +21,9 @@ class TransferPageWrapper extends StatelessWidget implements AutoRouteWrapper { return MultiBlocProvider( providers: [ - BlocProvider( + BlocProvider( // We are not calculating fees now - create: (final _) => TransferInfoCubit( + create: (final _) => TransferInfoBloc( metaDTO: metadata, appService: appService, )..init(), diff --git a/lib/features/wallet_screen/presentation/transfer_page/utils/dismiss_function.dart b/lib/features/wallet_screen/presentation/transfer_page/utils/dismiss_function.dart index 33feee4d..90e43bff 100644 --- a/lib/features/wallet_screen/presentation/transfer_page/utils/dismiss_function.dart +++ b/lib/features/wallet_screen/presentation/transfer_page/utils/dismiss_function.dart @@ -1,6 +1,6 @@ import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; -import 'package:threedpass/features/wallet_screen/bloc/transfer_info_cubit.dart'; +import 'package:threedpass/features/wallet_screen/bloc/transfer_info_bloc.dart'; class DismissFunctionFabric { final BuildContext context; @@ -8,12 +8,12 @@ class DismissFunctionFabric { const DismissFunctionFabric(this.context); void Function() buildToAddress(final ToAddressData data) { - final transferInfoCubit = BlocProvider.of(context); - return () => transferInfoCubit.removeToAddress(data); + final transferInfoCubit = BlocProvider.of(context); + return () => transferInfoCubit.add(RemoveToAddressEvent(data)); } void Function() buildFromAddress(final FromAddressData data) { - final transferInfoCubit = BlocProvider.of(context); - return () => transferInfoCubit.removeFromAddress(data); + final transferInfoCubit = BlocProvider.of(context); + return () => transferInfoCubit.add(RemoveFromAddressEvent(data)); } } diff --git a/lib/features/wallet_screen/presentation/transfer_page/widgets/add_card_basic.dart b/lib/features/wallet_screen/presentation/transfer_page/widgets/add_card_basic.dart index 9669a2e1..c860ace7 100644 --- a/lib/features/wallet_screen/presentation/transfer_page/widgets/add_card_basic.dart +++ b/lib/features/wallet_screen/presentation/transfer_page/widgets/add_card_basic.dart @@ -3,7 +3,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:threedpass/core/theme/d3p_special_styles.dart'; import 'package:threedpass/core/widgets/buttons/icon_button.dart'; -import 'package:threedpass/features/wallet_screen/bloc/transfer_info_cubit.dart'; +import 'package:threedpass/features/wallet_screen/bloc/transfer_info_bloc.dart'; class AddCardRowBasic extends StatelessWidget { const AddCardRowBasic({ @@ -15,12 +15,12 @@ class AddCardRowBasic extends StatelessWidget { final void Function() onPressed; final String unlocalizedText; - final bool Function(TransferInfo state) condition; + final bool Function(TransferInfoBlocState state) condition; @override Widget build(final BuildContext context) { final textStyles = Theme.of(context).customTextStyles; - return BlocBuilder( + return BlocBuilder( builder: (final context, final state) { if (condition(state)) { return Padding( diff --git a/lib/features/wallet_screen/presentation/transfer_page/widgets/add_from_card_row.dart b/lib/features/wallet_screen/presentation/transfer_page/widgets/add_from_card_row.dart index 808adfba..74986abf 100644 --- a/lib/features/wallet_screen/presentation/transfer_page/widgets/add_from_card_row.dart +++ b/lib/features/wallet_screen/presentation/transfer_page/widgets/add_from_card_row.dart @@ -1,7 +1,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:threedpass/core/polkawallet/bloc/app_service_cubit.dart'; -import 'package:threedpass/features/wallet_screen/bloc/transfer_info_cubit.dart'; +import 'package:threedpass/features/wallet_screen/bloc/transfer_info_bloc.dart'; import 'package:threedpass/features/wallet_screen/presentation/transfer_page/widgets/add_card_basic.dart'; class AddFromCardRow extends StatelessWidget { @@ -11,13 +11,13 @@ class AddFromCardRow extends StatelessWidget { @override Widget build(final BuildContext context) { - final transferInfoCubit = BlocProvider.of(context); + final transferInfoBloc = BlocProvider.of(context); final appServiceLoaderCubit = BlocProvider.of(context); final accAmount = appServiceLoaderCubit.state.keyring.allAccounts.length; return AddCardRowBasic( - onPressed: () => transferInfoCubit.addFromAddress(), + onPressed: () => transferInfoBloc.add(const AddFromAddressEvent()), unlocalizedText: 'add_account_from_label', condition: (final state) => state.screenType == TransferScreenType.many_to_one && diff --git a/lib/features/wallet_screen/presentation/transfer_page/widgets/add_to_card_row.dart b/lib/features/wallet_screen/presentation/transfer_page/widgets/add_to_card_row.dart index 097aafcb..d60b92da 100644 --- a/lib/features/wallet_screen/presentation/transfer_page/widgets/add_to_card_row.dart +++ b/lib/features/wallet_screen/presentation/transfer_page/widgets/add_to_card_row.dart @@ -1,6 +1,6 @@ import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; -import 'package:threedpass/features/wallet_screen/bloc/transfer_info_cubit.dart'; +import 'package:threedpass/features/wallet_screen/bloc/transfer_info_bloc.dart'; import 'package:threedpass/features/wallet_screen/presentation/transfer_page/widgets/add_card_basic.dart'; class AddToCardRow extends StatelessWidget { @@ -10,9 +10,9 @@ class AddToCardRow extends StatelessWidget { @override Widget build(final BuildContext context) { - final transferInfoCubit = BlocProvider.of(context); + final transferInfoBloc = BlocProvider.of(context); return AddCardRowBasic( - onPressed: () => transferInfoCubit.addToAddress(), + onPressed: () => transferInfoBloc.add(const AddToAddressEvent()), unlocalizedText: 'add_account_to_label', condition: (final state) => state.screenType == TransferScreenType.one_to_many || diff --git a/lib/features/wallet_screen/presentation/transfer_page/widgets/fees_text.dart b/lib/features/wallet_screen/presentation/transfer_page/widgets/fees_text.dart index 1eaf9563..4250e04b 100644 --- a/lib/features/wallet_screen/presentation/transfer_page/widgets/fees_text.dart +++ b/lib/features/wallet_screen/presentation/transfer_page/widgets/fees_text.dart @@ -4,7 +4,7 @@ import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_platform_widgets/flutter_platform_widgets.dart'; import 'package:threedpass/core/polkawallet/utils/balance_utils.dart'; import 'package:threedpass/core/widgets/text/d3p_body_large_text.dart'; -import 'package:threedpass/features/wallet_screen/bloc/transfer_info_cubit.dart'; +import 'package:threedpass/features/wallet_screen/bloc/transfer_info_bloc.dart'; class FeesText extends StatelessWidget { const FeesText({ @@ -13,7 +13,7 @@ class FeesText extends StatelessWidget { @override Widget build(final BuildContext context) { - return BlocBuilder( + return BlocBuilder( builder: (final context, final state) { return Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, diff --git a/lib/features/wallet_screen/presentation/transfer_page/widgets/from_address_textfield.dart b/lib/features/wallet_screen/presentation/transfer_page/widgets/from_address_textfield.dart index 4a912948..4aa4199a 100644 --- a/lib/features/wallet_screen/presentation/transfer_page/widgets/from_address_textfield.dart +++ b/lib/features/wallet_screen/presentation/transfer_page/widgets/from_address_textfield.dart @@ -12,7 +12,7 @@ import 'package:threedpass/core/widgets/buttons/elevated_button.dart'; import 'package:threedpass/core/widgets/buttons/enum_button.dart'; import 'package:threedpass/core/widgets/paddings.dart'; import 'package:threedpass/core/widgets/text/d3p_body_medium_text.dart'; -import 'package:threedpass/features/wallet_screen/bloc/transfer_info_cubit.dart'; +import 'package:threedpass/features/wallet_screen/bloc/transfer_info_bloc.dart'; class FromAddressTextField extends StatelessWidget { const FromAddressTextField({ @@ -87,7 +87,7 @@ class FromAddressTextField extends StatelessWidget { .keyring .allAccounts; final chosenFromAddresses = - BlocProvider.of(context).state.fromAddresses; + BlocProvider.of(context).state.fromAddresses; final accounts = AccountsList( allAccounts: allAccounts, @@ -127,8 +127,9 @@ class FromAddressTextField extends StatelessWidget { } void onAccountChoose(final BuildContext context, final KeyPairData acc) { - final transferInfoCubit = BlocProvider.of(context); - transferInfoCubit.changeChosenAccount(data, acc); + final transferInfoCubit = BlocProvider.of(context); + transferInfoCubit + .add(ChangeChosenAccountEvent(acc: acc, dataToChange: data)); Navigator.of(context).pop(); } } diff --git a/lib/features/wallet_screen/presentation/transfer_page/widgets/from_card_basic.dart b/lib/features/wallet_screen/presentation/transfer_page/widgets/from_card_basic.dart index 48fab434..96559a14 100644 --- a/lib/features/wallet_screen/presentation/transfer_page/widgets/from_card_basic.dart +++ b/lib/features/wallet_screen/presentation/transfer_page/widgets/from_card_basic.dart @@ -1,6 +1,6 @@ import 'package:flutter/material.dart'; import 'package:threedpass/core/widgets/paddings.dart'; -import 'package:threedpass/features/wallet_screen/bloc/transfer_info_cubit.dart'; +import 'package:threedpass/features/wallet_screen/bloc/transfer_info_bloc.dart'; import 'package:threedpass/features/wallet_screen/presentation/transfer_page/widgets/from_address_textfield.dart'; import 'package:threedpass/features/wallet_screen/presentation/transfer_page/widgets/password_textfield.dart'; diff --git a/lib/features/wallet_screen/presentation/transfer_page/widgets/from_card_many_to_one.dart b/lib/features/wallet_screen/presentation/transfer_page/widgets/from_card_many_to_one.dart index f4499567..ee4403fe 100644 --- a/lib/features/wallet_screen/presentation/transfer_page/widgets/from_card_many_to_one.dart +++ b/lib/features/wallet_screen/presentation/transfer_page/widgets/from_card_many_to_one.dart @@ -1,6 +1,6 @@ import 'package:flutter/material.dart'; import 'package:threedpass/core/widgets/paddings.dart'; -import 'package:threedpass/features/wallet_screen/bloc/transfer_info_cubit.dart'; +import 'package:threedpass/features/wallet_screen/bloc/transfer_info_bloc.dart'; import 'package:threedpass/features/wallet_screen/domain/entities/transfer_meta_dto.dart'; import 'package:threedpass/features/wallet_screen/presentation/transfer_page/utils/dismiss_function.dart'; import 'package:threedpass/features/wallet_screen/presentation/transfer_page/widgets/amount_textfield.dart'; @@ -38,7 +38,7 @@ class FromCardManyToOne extends StatelessWidget { AmountTextFieldBuilder( amountController: sendAmountData.amountController, transferType: metaInfoType, - balance: 0, // TODO + balance: sendAmountData.balance ?? 0, ), ], ), diff --git a/lib/features/wallet_screen/presentation/transfer_page/widgets/from_card_one_to_many.dart b/lib/features/wallet_screen/presentation/transfer_page/widgets/from_card_one_to_many.dart index 2a26b919..2e890724 100644 --- a/lib/features/wallet_screen/presentation/transfer_page/widgets/from_card_one_to_many.dart +++ b/lib/features/wallet_screen/presentation/transfer_page/widgets/from_card_one_to_many.dart @@ -1,5 +1,5 @@ import 'package:flutter/material.dart'; -import 'package:threedpass/features/wallet_screen/bloc/transfer_info_cubit.dart'; +import 'package:threedpass/features/wallet_screen/bloc/transfer_info_bloc.dart'; import 'package:threedpass/features/wallet_screen/presentation/transfer_page/utils/dismiss_function.dart'; import 'package:threedpass/features/wallet_screen/presentation/transfer_page/widgets/basic_transfer_block.dart'; import 'package:threedpass/features/wallet_screen/presentation/transfer_page/widgets/from_card_basic.dart'; diff --git a/lib/features/wallet_screen/presentation/transfer_page/widgets/froms_list_view.dart b/lib/features/wallet_screen/presentation/transfer_page/widgets/froms_list_view.dart index 7050c24e..bf2aad27 100644 --- a/lib/features/wallet_screen/presentation/transfer_page/widgets/froms_list_view.dart +++ b/lib/features/wallet_screen/presentation/transfer_page/widgets/froms_list_view.dart @@ -1,5 +1,5 @@ import 'package:flutter/material.dart'; -import 'package:threedpass/features/wallet_screen/bloc/transfer_info_cubit.dart'; +import 'package:threedpass/features/wallet_screen/bloc/transfer_info_bloc.dart'; import 'package:threedpass/features/wallet_screen/domain/entities/transfer_meta_dto.dart'; import 'package:threedpass/features/wallet_screen/presentation/transfer_page/widgets/from_card_many_to_one.dart'; import 'package:threedpass/features/wallet_screen/presentation/transfer_page/widgets/from_card_one_to_many.dart'; @@ -12,7 +12,7 @@ class FromsListView extends StatelessWidget { super.key, }); - final TransferInfo transferInfo; + final TransferInfoBlocState transferInfo; final MetaInfoType metaInfoType; @override diff --git a/lib/features/wallet_screen/presentation/transfer_page/widgets/make_transfer_button.dart b/lib/features/wallet_screen/presentation/transfer_page/widgets/make_transfer_button.dart index 83705c36..b95f8324 100644 --- a/lib/features/wallet_screen/presentation/transfer_page/widgets/make_transfer_button.dart +++ b/lib/features/wallet_screen/presentation/transfer_page/widgets/make_transfer_button.dart @@ -3,26 +3,17 @@ part of '../transfer_page.dart'; class _MakeTransferButton extends StatelessWidget { const _MakeTransferButton({ required this.formKey, - required this.amountController, - required this.passwordController, - required this.toAddressController, required this.appService, final Key? key, }) : super(key: key); - final TextEditingController toAddressController; - final TextEditingController amountController; - final TextEditingController passwordController; final GlobalKey formKey; final AppService appService; Future onPressed(final BuildContext context) async { - final transferInfoMeta = BlocProvider.of(context); + final transferInfoMeta = BlocProvider.of(context); await transferInfoMeta.sendTransfer( - toAddress: toAddressController.text, - amount: amountController.text, - password: passwordController.text, formKey: formKey, context: context, ); @@ -30,7 +21,7 @@ class _MakeTransferButton extends StatelessWidget { @override Widget build(final BuildContext context) { - return BlocBuilder( + return BlocBuilder( builder: (final context, final state) => D3pElevatedButton( text: 'make_transfer_label'.tr(), onPressed: state != null diff --git a/lib/features/wallet_screen/presentation/transfer_page/widgets/password_textfield.dart b/lib/features/wallet_screen/presentation/transfer_page/widgets/password_textfield.dart index 836b1dc2..25c80c7a 100644 --- a/lib/features/wallet_screen/presentation/transfer_page/widgets/password_textfield.dart +++ b/lib/features/wallet_screen/presentation/transfer_page/widgets/password_textfield.dart @@ -2,7 +2,7 @@ import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:threedpass/core/utils/validators.dart'; -import 'package:threedpass/features/wallet_screen/bloc/transfer_info_cubit.dart'; +import 'package:threedpass/features/wallet_screen/bloc/transfer_info_bloc.dart'; import 'package:threedpass/features/wallet_screen/presentation/transfer_page/widgets/basic_transfer_textfield.dart'; import 'package:threedpass/features/wallet_screen/presentation/transfer_page/widgets/password_hint.dart'; @@ -54,8 +54,8 @@ class _State extends State { }); } - void onLabelButtonPressed(BuildContext context) { - final transferInfo = BlocProvider.of(context); - transferInfo.copyPasswordIn(widget.data); + void onLabelButtonPressed(final BuildContext context) { + final transferInfo = BlocProvider.of(context); + transferInfo.add(CopyPasswordEvent(widget.data)); } } diff --git a/lib/features/wallet_screen/presentation/transfer_page/widgets/to_card_basic.dart b/lib/features/wallet_screen/presentation/transfer_page/widgets/to_card_basic.dart index cc534039..0b9e3131 100644 --- a/lib/features/wallet_screen/presentation/transfer_page/widgets/to_card_basic.dart +++ b/lib/features/wallet_screen/presentation/transfer_page/widgets/to_card_basic.dart @@ -1,5 +1,5 @@ import 'package:flutter/material.dart'; -import 'package:threedpass/features/wallet_screen/bloc/transfer_info_cubit.dart'; +import 'package:threedpass/features/wallet_screen/bloc/transfer_info_bloc.dart'; import 'package:threedpass/features/wallet_screen/presentation/transfer_page/widgets/to_address_textfield.dart'; class ToCardBasic extends StatelessWidget { diff --git a/lib/features/wallet_screen/presentation/transfer_page/widgets/to_card_many_to_one.dart b/lib/features/wallet_screen/presentation/transfer_page/widgets/to_card_many_to_one.dart index 82e71f1d..9e84f880 100644 --- a/lib/features/wallet_screen/presentation/transfer_page/widgets/to_card_many_to_one.dart +++ b/lib/features/wallet_screen/presentation/transfer_page/widgets/to_card_many_to_one.dart @@ -1,5 +1,5 @@ import 'package:flutter/material.dart'; -import 'package:threedpass/features/wallet_screen/bloc/transfer_info_cubit.dart'; +import 'package:threedpass/features/wallet_screen/bloc/transfer_info_bloc.dart'; import 'package:threedpass/features/wallet_screen/presentation/transfer_page/utils/dismiss_function.dart'; import 'package:threedpass/features/wallet_screen/presentation/transfer_page/widgets/basic_transfer_block.dart'; import 'package:threedpass/features/wallet_screen/presentation/transfer_page/widgets/to_card_basic.dart'; diff --git a/lib/features/wallet_screen/presentation/transfer_page/widgets/to_card_one_to_many.dart b/lib/features/wallet_screen/presentation/transfer_page/widgets/to_card_one_to_many.dart index e08c4e46..3d319880 100644 --- a/lib/features/wallet_screen/presentation/transfer_page/widgets/to_card_one_to_many.dart +++ b/lib/features/wallet_screen/presentation/transfer_page/widgets/to_card_one_to_many.dart @@ -1,6 +1,6 @@ import 'package:flutter/material.dart'; import 'package:threedpass/core/widgets/paddings.dart'; -import 'package:threedpass/features/wallet_screen/bloc/transfer_info_cubit.dart'; +import 'package:threedpass/features/wallet_screen/bloc/transfer_info_bloc.dart'; import 'package:threedpass/features/wallet_screen/domain/entities/transfer_meta_dto.dart'; import 'package:threedpass/features/wallet_screen/presentation/transfer_page/utils/dismiss_function.dart'; import 'package:threedpass/features/wallet_screen/presentation/transfer_page/widgets/amount_textfield.dart'; @@ -36,7 +36,7 @@ class ToCardOneToMany extends StatelessWidget { AmountTextFieldBuilder( amountController: sendAmountData.amountController, transferType: metaInfoType, - balance: 0, // TODO + balance: sendAmountData.balance ?? 0, ), ], ), diff --git a/lib/features/wallet_screen/presentation/transfer_page/widgets/tos_list_view.dart b/lib/features/wallet_screen/presentation/transfer_page/widgets/tos_list_view.dart index 177acf25..4cc1f02e 100644 --- a/lib/features/wallet_screen/presentation/transfer_page/widgets/tos_list_view.dart +++ b/lib/features/wallet_screen/presentation/transfer_page/widgets/tos_list_view.dart @@ -1,5 +1,5 @@ import 'package:flutter/material.dart'; -import 'package:threedpass/features/wallet_screen/bloc/transfer_info_cubit.dart'; +import 'package:threedpass/features/wallet_screen/bloc/transfer_info_bloc.dart'; import 'package:threedpass/features/wallet_screen/domain/entities/transfer_meta_dto.dart'; import 'package:threedpass/features/wallet_screen/presentation/transfer_page/widgets/to_card_many_to_one.dart'; import 'package:threedpass/features/wallet_screen/presentation/transfer_page/widgets/to_card_one_to_many.dart'; @@ -12,7 +12,7 @@ class ToListView extends StatelessWidget { super.key, }); - final TransferInfo transferInfo; + final TransferInfoBlocState transferInfo; final MetaInfoType metaInfoType; @override diff --git a/lib/features/wallet_screen/presentation/transfer_page/widgets/transfer_page_content.dart b/lib/features/wallet_screen/presentation/transfer_page/widgets/transfer_page_content.dart new file mode 100644 index 00000000..062f0e76 --- /dev/null +++ b/lib/features/wallet_screen/presentation/transfer_page/widgets/transfer_page_content.dart @@ -0,0 +1,58 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:threedpass/core/widgets/paddings.dart'; +import 'package:threedpass/features/wallet_screen/bloc/transfer_info_bloc.dart'; +import 'package:threedpass/features/wallet_screen/presentation/transfer_page/widgets/add_from_card_row.dart'; +import 'package:threedpass/features/wallet_screen/presentation/transfer_page/widgets/add_to_card_row.dart'; +import 'package:threedpass/features/wallet_screen/presentation/transfer_page/widgets/froms_list_view.dart'; +import 'package:threedpass/features/wallet_screen/presentation/transfer_page/widgets/tos_list_view.dart'; +import 'package:threedpass/features/wallet_screen/presentation/transfer_page/widgets/transfer_type_switch.dart'; + +class TransferPageAddressesList extends StatelessWidget { + const TransferPageAddressesList({ + required this.state, + super.key, + }); + + final TransferInfoBlocState state; + + @override + Widget build(final BuildContext context) { + final transferInfo = BlocProvider.of(context); + + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const SizedBoxH8(), + FromsListView( + transferInfo: state, + metaInfoType: transferInfo.metaDTO.type, + ), + const AddFromCardRow(), + const _ArrowFromTo(), + ToListView( + transferInfo: state, + metaInfoType: transferInfo.metaDTO.type, + ), + const AddToCardRow(), + const TransferTypeSwitch(), + const SizedBox(height: 72), + ], + ); + } +} + +class _ArrowFromTo extends StatelessWidget { + const _ArrowFromTo(); + + @override + Widget build(final BuildContext context) { + return const Align( + alignment: Alignment.center, + child: Icon( + Icons.arrow_downward_outlined, + size: 30, + ), + ); + } +} diff --git a/lib/features/wallet_screen/presentation/transfer_page/widgets/transfer_type_switch.dart b/lib/features/wallet_screen/presentation/transfer_page/widgets/transfer_type_switch.dart index 1cad783f..d92dc011 100644 --- a/lib/features/wallet_screen/presentation/transfer_page/widgets/transfer_type_switch.dart +++ b/lib/features/wallet_screen/presentation/transfer_page/widgets/transfer_type_switch.dart @@ -3,7 +3,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:threedpass/core/polkawallet/utils/transfer_type.dart'; import 'package:threedpass/core/widgets/input/switch_button.dart'; -import 'package:threedpass/features/wallet_screen/bloc/transfer_info_cubit.dart'; +import 'package:threedpass/features/wallet_screen/bloc/transfer_info_bloc.dart'; class TransferTypeSwitch extends StatelessWidget { const TransferTypeSwitch({ @@ -12,14 +12,15 @@ class TransferTypeSwitch extends StatelessWidget { void onChanged(final BuildContext context, final TransactionOption? value) { if (value != null) { - BlocProvider.of(context).updateTransferType(value); + BlocProvider.of(context) + .add(UpdateTransferTypeEvent(value)); } } @override Widget build(final BuildContext context) { final initialValue = - BlocProvider.of(context).state.type == + BlocProvider.of(context).state.transactionOption == TransactionOption.transferKeepAlive; return Padding( padding: const EdgeInsets.symmetric(horizontal: 8), From b1749e85f483f5134787684571ffaa9a50e33375 Mon Sep 17 00:00:00 2001 From: L3odr0id Date: Mon, 30 Oct 2023 09:20:32 +0300 Subject: [PATCH 6/7] FEATURE: Multitransfers --- .../polkawallet/bloc/app_service_cubit.dart | 2 +- lib/core/polkawallet/utils/transfer_type.dart | 28 +- lib/core/polkawallet/utils/tx_info.dart | 84 ++---- lib/core/polkawallet/utils/tx_params.dart | 84 ++++++ .../utils/tx_update_event_logs_handler.dart | 38 ++- lib/core/widgets/buttons/elevated_button.dart | 3 + .../bloc/meta_tx_infos_fabric.dart | 178 ++++++++++++ .../bloc/notifications_cubit.dart | 10 +- .../bloc/notifications_cubit.g.dart | 31 +- .../bloc/transfer_info_bloc.dart | 186 ++++++++---- .../bloc/transfer_info_bloc.g.dart | 218 +++++++------- .../bloc/transfer_info_bloc_event.dart | 2 +- .../transfer_info_bloc_fields_events.dart | 10 +- .../bloc/transfer_info_bloc_state.dart | 4 +- .../domain/entities/multitransfer_atom.dart | 61 ---- .../domain/entities/transaction.dart | 188 ++++++++++++ .../domain/entities/transfer.dart | 270 +++++++++++------- .../domain/entities/transfer_meta_dto.dart | 38 +-- .../widgets/coin_transfer_button.dart | 2 + .../non_native_tokens/non_native_tokens.dart | 53 ++-- .../widgets/asset_transfer_button.dart | 21 +- .../widgets/notifcation_transfer.dart | 64 ++++- .../transfer_page/widgets/add_card_basic.dart | 70 ++--- .../widgets/add_to_card_row.dart | 18 +- .../widgets/amount_textfield.dart | 33 ++- .../widgets/from_address_textfield.dart | 1 + .../widgets/from_card_many_to_one.dart | 2 +- .../widgets/to_card_one_to_many.dart | 4 +- .../widgets/transfer_type_switch.dart | 13 +- pubspec.lock | 4 +- pubspec.yaml | 2 +- 31 files changed, 1150 insertions(+), 572 deletions(-) create mode 100644 lib/core/polkawallet/utils/tx_params.dart create mode 100644 lib/features/wallet_screen/bloc/meta_tx_infos_fabric.dart delete mode 100644 lib/features/wallet_screen/domain/entities/multitransfer_atom.dart create mode 100644 lib/features/wallet_screen/domain/entities/transaction.dart diff --git a/lib/core/polkawallet/bloc/app_service_cubit.dart b/lib/core/polkawallet/bloc/app_service_cubit.dart index fcf2ba54..f2ad66bc 100644 --- a/lib/core/polkawallet/bloc/app_service_cubit.dart +++ b/lib/core/polkawallet/bloc/app_service_cubit.dart @@ -199,7 +199,7 @@ class AppServiceLoaderCubit extends Cubit { void addHandler( final String msgId, - final void Function(String) setTransactionResult, + final TransactionsCallback setTransactionResult, ) { state.plugin.sdk.webView!.addGlobalHandler( TxUpdateEventLogsHandler(msgId, setTransactionResult), diff --git a/lib/core/polkawallet/utils/transfer_type.dart b/lib/core/polkawallet/utils/transfer_type.dart index b8723478..689d62dc 100644 --- a/lib/core/polkawallet/utils/transfer_type.dart +++ b/lib/core/polkawallet/utils/transfer_type.dart @@ -1,18 +1,18 @@ -class TransferTypeValue { - static const TransactionOption defaultType = - TransactionOption.transferKeepAlive; +// class TransferTypeValue { +// static const TransactionOption defaultType = +// TransactionOption.transferKeepAlive; - const TransferTypeValue(this.type); +// const TransferTypeValue(this.type); - final TransactionOption type; +// final TransactionOption type; - @override - String toString() { - return type.name; - } -} +// @override +// String toString() { +// return type.name; +// } +// } -enum TransactionOption { - transfer, - transferKeepAlive, -} +// enum TransactionOption { +// transfer, +// transferKeepAlive, +// } diff --git a/lib/core/polkawallet/utils/tx_info.dart b/lib/core/polkawallet/utils/tx_info.dart index 086babae..62b38477 100644 --- a/lib/core/polkawallet/utils/tx_info.dart +++ b/lib/core/polkawallet/utils/tx_info.dart @@ -1,73 +1,54 @@ -// import 'package:logger/logger.dart'; // import 'package:polkawallet_sdk/api/types/txInfoData.dart'; // import 'package:polkawallet_sdk/plugin/store/balances.dart'; // import 'package:polkawallet_sdk/storage/types/keyPairData.dart'; -// import 'package:threedpass/core/polkawallet/utils/balance_utils.dart'; // import 'package:threedpass/core/polkawallet/utils/transfer_type.dart'; -// import 'package:threedpass/setup.dart'; +// import 'package:threedpass/core/polkawallet/utils/tx_params.dart'; // abstract class TransferTxInfoI { // final KeyPairData senderData; // final int decimals; +// final TransactionOption transferType; +// final String toAddress; +// final double amount; // const TransferTxInfoI({ // required this.decimals, // required this.senderData, +// required this.amount, +// required this.toAddress, +// required this.transferType, // }); -// TxInfoData txInfo( -// final TransactionOption transferType, -// ); -// List params(final String? amount, final String toAddress); +// TxInfoData txInfo(); +// TxParams params(); // } // class AssetsTransferTx extends TransferTxInfoI { // final TokenBalanceData tokenBalanceData; + // const AssetsTransferTx({ // required super.decimals, // required super.senderData, +// required super.amount, +// required super.toAddress, +// required super.transferType, // required this.tokenBalanceData, // }); // @override -// TxInfoData txInfo( -// final TransactionOption transferType, -// ) => -// TxInfoData( +// TxInfoData txInfo() => TxInfoData( // 'assets', // TransferTypeValue(transferType).toString(), // TxSenderData(senderData.address, senderData.pubKey), // ); // @override -// List params( -// final String? amount, -// final String toAddress, -// ) { -// // https://polkadot.js.org/docs/substrate/extrinsics/#transferid-compactu32-target-multiaddress-amount-compactu128 - -// if (tokenBalanceData.decimals == null) { -// getIt().w( -// 'DANGER! tokenBalanceData.decimals is null when get params for AssetsTransferTx.', -// ); -// } - -// final realAmount = BalanceUtils.tokenInt( -// amount, -// tokenBalanceData.decimals ?? decimals, +// TxParams params() { +// return AssetsTxParams( +// amount: amount, +// toAddress: toAddress, +// tokenBalanceData: tokenBalanceData, // ); - -// if (tokenBalanceData.id == null) { -// throw Exception('TokenBalanceData.id is null'); -// } - -// return [ -// tokenBalanceData.id!, -// // params.to -// toAddress, -// // params.amount -// realAmount.toString(), -// ]; // } // } @@ -75,13 +56,13 @@ // const CoinsTransferTx({ // required super.decimals, // required super.senderData, +// required super.amount, +// required super.toAddress, +// required super.transferType, // }); // @override -// TxInfoData txInfo( -// final TransactionOption transferType, -// ) => -// TxInfoData( +// TxInfoData txInfo() => TxInfoData( // 'balances', // TransferTypeValue(transferType).toString(), // TxSenderData( @@ -91,20 +72,11 @@ // ); // @override -// List params( -// final String? amount, -// final String toAddress, -// ) { -// final realAmount = BalanceUtils.tokenInt( -// amount, -// decimals, +// TxParams params() { +// return CoinsTxParams( +// amount: amount, +// decimals: decimals, +// toAddress: toAddress, // ); - -// return [ -// // params.to -// toAddress, -// // params.amount -// realAmount.toString(), -// ]; // } // } diff --git a/lib/core/polkawallet/utils/tx_params.dart b/lib/core/polkawallet/utils/tx_params.dart new file mode 100644 index 00000000..97016019 --- /dev/null +++ b/lib/core/polkawallet/utils/tx_params.dart @@ -0,0 +1,84 @@ +// import 'package:polkawallet_sdk/plugin/store/balances.dart'; +// import 'package:threedpass/core/polkawallet/utils/balance_utils.dart'; + +// abstract class TxParams { +// const TxParams(); + +// List paramsToSend(); +// String get toAddress; +// double get amount; + +// TxParamsType get type; +// } + +// class CoinsTxParams extends TxParams { +// const CoinsTxParams({ +// required this.amount, +// required this.decimals, +// required this.toAddress, +// }); + +// @override +// final double amount; +// final int decimals; +// @override +// final String toAddress; + +// @override +// List paramsToSend() { +// final realAmount = BalanceUtils.tokenInt( +// amount.toString(), +// decimals, +// ); + +// return [ +// // params.to +// toAddress, +// // params.amount +// realAmount.toString(), +// ]; +// } + +// @override +// TxParamsType get type => TxParamsType.coins; +// } + +// class AssetsTxParams extends TxParams { +// const AssetsTxParams({ +// required this.amount, +// required this.toAddress, +// required this.tokenBalanceData, +// }); + +// final TokenBalanceData tokenBalanceData; +// @override +// final double amount; +// @override +// final String toAddress; + +// @override +// List paramsToSend() { +// // https://polkadot.js.org/docs/substrate/extrinsics/#transferid-compactu32-target-multiaddress-amount-compactu128 +// final realAmount = BalanceUtils.tokenInt( +// amount.toString(), +// tokenBalanceData.decimals ?? 0, +// ); + +// if (tokenBalanceData.id == null) { +// throw Exception('TokenBalanceData.id is null'); +// } + +// return [ +// tokenBalanceData.id!, +// // params.to +// toAddress, +// // params.amount +// realAmount.toString(), +// ]; +// } + +// @override +// TxParamsType get type => TxParamsType.assets; +// } + +// enum TxParamsType { coins, assets } diff --git a/lib/core/polkawallet/utils/tx_update_event_logs_handler.dart b/lib/core/polkawallet/utils/tx_update_event_logs_handler.dart index 107f0e77..dc366835 100644 --- a/lib/core/polkawallet/utils/tx_update_event_logs_handler.dart +++ b/lib/core/polkawallet/utils/tx_update_event_logs_handler.dart @@ -1,6 +1,15 @@ import 'dart:convert'; +import 'package:flutter/material.dart'; +import 'package:logger/logger.dart'; import 'package:polkawallet_sdk/utils/web_logs_handler.dart'; +import 'package:threedpass/features/wallet_screen/domain/entities/transfer_history_ui.dart'; +import 'package:threedpass/setup.dart'; + +typedef TransactionsCallback = void Function({ + required ExtrisincStatus status, + required String? message, +}); class TxUpdateEventLogsHandler extends WebLogsHandler { const TxUpdateEventLogsHandler( @@ -10,8 +19,7 @@ class TxUpdateEventLogsHandler extends WebLogsHandler { final String msgId; - /// @param {String} is extrinsicSuccess or message - final void Function(String) setTransactionResult; + final TransactionsCallback setTransactionResult; static const String extrinsicSuccess = 'ok'; @@ -40,10 +48,32 @@ class TxUpdateEventLogsHandler extends WebLogsHandler { } final String title = dataSection['title'] as String; + final String message = dataSection['message'] as String; + debugPrint('$title $message'); + if (title == "system.ExtrinsicSuccess") { - setTransactionResult(extrinsicSuccess); + getIt().d('Found ExtrinsicSuccess for $msgId'); + setTransactionResult(status: ExtrisincStatus.success, message: null); } else if (title == 'system.ExtrinsicFailed') { - setTransactionResult(dataSection['message'] as String); + getIt().d('Found ExtrinsicFailed for $msgId'); + setTransactionResult( + status: ExtrisincStatus.failed, + message: message, + ); + } + + if (title.contains('error')) { + if (message.contains('password check failed')) { + setTransactionResult( + status: ExtrisincStatus.error, + message: message, + ); + } else { + setTransactionResult( + status: ExtrisincStatus.failed, + message: message, + ); + } } } } diff --git a/lib/core/widgets/buttons/elevated_button.dart b/lib/core/widgets/buttons/elevated_button.dart index 9a40b0e7..400fb1d1 100644 --- a/lib/core/widgets/buttons/elevated_button.dart +++ b/lib/core/widgets/buttons/elevated_button.dart @@ -17,6 +17,7 @@ class D3pElevatedButton extends StatelessWidget { this.childAlignment, this.textStyle, this.child, + this.shape, }) : super(key: key); final void Function()? onPressed; @@ -31,6 +32,7 @@ class D3pElevatedButton extends StatelessWidget { final MainAxisAlignment? childAlignment; final TextStyle? textStyle; final Widget? child; + final OutlinedBorder? shape; @override Widget build(final BuildContext context) { @@ -61,6 +63,7 @@ class D3pElevatedButton extends StatelessWidget { padding: MaterialStateProperty.all( const EdgeInsets.symmetric(horizontal: 8), ), + shape: shape != null ? MaterialStateProperty.all(shape) : null, textStyle: textStyle != null ? MaterialStateProperty.all( textStyle, diff --git a/lib/features/wallet_screen/bloc/meta_tx_infos_fabric.dart b/lib/features/wallet_screen/bloc/meta_tx_infos_fabric.dart new file mode 100644 index 00000000..24a4188a --- /dev/null +++ b/lib/features/wallet_screen/bloc/meta_tx_infos_fabric.dart @@ -0,0 +1,178 @@ +part of 'transfer_info_bloc.dart'; + +class _MetaTxInfosFabric { + const _MetaTxInfosFabric({ + required this.metaDTO, + required this.state, + }); + + final TransferInfoBlocState state; + final TransferMetaDTO metaDTO; + + TransferTxInfoI buildTransferTxInfoI({ + required final int decimals, + required final KeyPairData senderData, + required final double amount, + required final String toAddress, + required final BalanceTransactionType transferType, + required final TokenBalanceData? tbd, + }) { + if (tbd == null) { + return CoinsTransferTx( + decimals: metaDTO.decimals, + senderData: senderData, + amount: amount, + toAddress: toAddress, + transferType: state.transactionOption, + ); + } else { + return AssetsTransferTx( + decimals: metaDTO.decimals, + senderData: senderData, + amount: amount, + toAddress: toAddress, + transferType: state.transactionOption, + tokenBalanceData: tbd, + ); + } + } + + List oneToOne(final TokenBalanceData? tbd) { + final res = []; + final from = state.fromAddresses.first; + final amount = state.amounts.first; + final to = state.toAddresses.first; + + if (from.data == null) { + throw Exception('The only FROM address is null'); + } + + final amountD = double.tryParse(amount.amountController.text); + if (amountD == null) { + throw Exception("Couldn't parse amount"); + } + + res.add( + buildTransferTxInfoI( + decimals: metaDTO.decimals, + senderData: from.data!, + amount: amountD, + toAddress: to.toAddressController.text, + transferType: state.transactionOption, + tbd: tbd, + ), + ); + return res; + } + + List oneToMany(final TokenBalanceData? tbd) { + final res = []; + + if (state.toAddresses.length != state.amounts.length) { + throw Exception( + 'The number of TO addresses must be equal to the number of amounts', + ); + } + + final from = state.fromAddresses.first; + if (from.data == null) { + throw Exception('The only FROM address is null'); + } + + for (var i = 0; i < state.toAddresses.length; i++) { + final amount = state.amounts[i]; + final to = state.toAddresses[i]; + + final amountD = double.tryParse(amount.amountController.text); + if (amountD == null) { + throw Exception("Couldn't parse amount"); + } + + res.add( + buildTransferTxInfoI( + decimals: metaDTO.decimals, + senderData: from.data!, + amount: amountD, + toAddress: to.toAddressController.text, + transferType: state.transactionOption, + tbd: tbd, + ), + ); + } + + return res; + } + + List manyToOne(final TokenBalanceData? tbd) { + final res = []; + + if (state.fromAddresses.length != state.amounts.length) { + throw Exception( + 'The number of FROM addresses must be equal to the number of amounts', + ); + } + + final toAddress = state.toAddresses.first.toAddressController.text; + + for (var i = 0; i < state.fromAddresses.length; i++) { + final from = state.fromAddresses[i]; + if (from.data == null) { + throw Exception('The FROM address [$i] is null'); + } + + final amount = state.amounts[i]; + final amountD = double.tryParse(amount.amountController.text); + if (amountD == null) { + throw Exception("Couldn't parse amount"); + } + + res.add( + buildTransferTxInfoI( + decimals: metaDTO.decimals, + senderData: from.data!, + amount: amountD, + toAddress: toAddress, + transferType: state.transactionOption, + tbd: tbd, + ), + ); + } + + return res; + } + + List buildList(final TokenBalanceData? tbd) { + final res = []; + caseSplit( + txInfos: state.fromAddresses, + params: state.toAddresses, + passwords: state.fromAddresses, + onFirst: () { + final tmp = oneToOne(tbd); + res.addAll(tmp); + }, + onSecond: () { + final tmp = oneToMany(tbd); + res.addAll(tmp); + }, + onThird: () { + final tmp = manyToOne(tbd); + res.addAll(tmp); + }, + onError: () { + throw Exception('Something went wrong'); + }, + ); + return res; + } + + List build() { + switch (metaDTO.type) { + case MetaInfoType.coin: + return buildList(null); + case MetaInfoType.asset: + final amDTO = metaDTO as AssetTransferMetaDTO; + return buildList(amDTO.tokenBalanceData); + } + } +} diff --git a/lib/features/wallet_screen/bloc/notifications_cubit.dart b/lib/features/wallet_screen/bloc/notifications_cubit.dart index cfb831e9..ca3c2ab3 100644 --- a/lib/features/wallet_screen/bloc/notifications_cubit.dart +++ b/lib/features/wallet_screen/bloc/notifications_cubit.dart @@ -8,8 +8,8 @@ enum NotificationType { transfer, vote } @CopyWith() class NotificationDTO { - final List? fromAddresses; - final List? toAddresses; + final String? fromAddress; + final String? toAddress; final String? amount; final NotificationType type; final ExtrisincStatus status; @@ -20,9 +20,9 @@ class NotificationDTO { const NotificationDTO({ required this.type, required this.status, - this.amount, - this.fromAddresses, - this.toAddresses, + required this.amount, + this.fromAddress, + this.toAddress, this.message, this.symbols, this.blockDateTime, diff --git a/lib/features/wallet_screen/bloc/notifications_cubit.g.dart b/lib/features/wallet_screen/bloc/notifications_cubit.g.dart index f8d3e76b..b2dce231 100644 --- a/lib/features/wallet_screen/bloc/notifications_cubit.g.dart +++ b/lib/features/wallet_screen/bloc/notifications_cubit.g.dart @@ -13,9 +13,9 @@ abstract class _$NotificationDTOCWProxy { NotificationDTO amount(String? amount); - NotificationDTO fromAddresses(List? fromAddresses); + NotificationDTO fromAddress(String? fromAddress); - NotificationDTO toAddresses(List? toAddresses); + NotificationDTO toAddress(String? toAddress); NotificationDTO message(String? message); @@ -33,8 +33,8 @@ abstract class _$NotificationDTOCWProxy { NotificationType? type, ExtrisincStatus? status, String? amount, - List? fromAddresses, - List? toAddresses, + String? fromAddress, + String? toAddress, String? message, String? symbols, DateTime? blockDateTime, @@ -57,12 +57,11 @@ class _$NotificationDTOCWProxyImpl implements _$NotificationDTOCWProxy { NotificationDTO amount(String? amount) => this(amount: amount); @override - NotificationDTO fromAddresses(List? fromAddresses) => - this(fromAddresses: fromAddresses); + NotificationDTO fromAddress(String? fromAddress) => + this(fromAddress: fromAddress); @override - NotificationDTO toAddresses(List? toAddresses) => - this(toAddresses: toAddresses); + NotificationDTO toAddress(String? toAddress) => this(toAddress: toAddress); @override NotificationDTO message(String? message) => this(message: message); @@ -86,8 +85,8 @@ class _$NotificationDTOCWProxyImpl implements _$NotificationDTOCWProxy { Object? type = const $CopyWithPlaceholder(), Object? status = const $CopyWithPlaceholder(), Object? amount = const $CopyWithPlaceholder(), - Object? fromAddresses = const $CopyWithPlaceholder(), - Object? toAddresses = const $CopyWithPlaceholder(), + Object? fromAddress = const $CopyWithPlaceholder(), + Object? toAddress = const $CopyWithPlaceholder(), Object? message = const $CopyWithPlaceholder(), Object? symbols = const $CopyWithPlaceholder(), Object? blockDateTime = const $CopyWithPlaceholder(), @@ -105,14 +104,14 @@ class _$NotificationDTOCWProxyImpl implements _$NotificationDTOCWProxy { ? _value.amount // ignore: cast_nullable_to_non_nullable : amount as String?, - fromAddresses: fromAddresses == const $CopyWithPlaceholder() - ? _value.fromAddresses + fromAddress: fromAddress == const $CopyWithPlaceholder() + ? _value.fromAddress // ignore: cast_nullable_to_non_nullable - : fromAddresses as List?, - toAddresses: toAddresses == const $CopyWithPlaceholder() - ? _value.toAddresses + : fromAddress as String?, + toAddress: toAddress == const $CopyWithPlaceholder() + ? _value.toAddress // ignore: cast_nullable_to_non_nullable - : toAddresses as List?, + : toAddress as String?, message: message == const $CopyWithPlaceholder() ? _value.message // ignore: cast_nullable_to_non_nullable diff --git a/lib/features/wallet_screen/bloc/transfer_info_bloc.dart b/lib/features/wallet_screen/bloc/transfer_info_bloc.dart index 8a227014..53725694 100644 --- a/lib/features/wallet_screen/bloc/transfer_info_bloc.dart +++ b/lib/features/wallet_screen/bloc/transfer_info_bloc.dart @@ -3,15 +3,25 @@ import 'dart:async'; import 'package:copy_with_extension/copy_with_extension.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:fluttertoast/fluttertoast.dart'; import 'package:polkawallet_sdk/api/types/txInfoData.dart'; +import 'package:polkawallet_sdk/p3d/balance_transaction_type.dart'; +import 'package:polkawallet_sdk/p3d/tx_info.dart'; +import 'package:polkawallet_sdk/plugin/store/balances.dart'; import 'package:polkawallet_sdk/storage/types/keyPairData.dart'; import 'package:super_core/super_core.dart'; import 'package:threedpass/core/polkawallet/app_service.dart'; +import 'package:threedpass/core/polkawallet/bloc/app_service_cubit.dart'; +import 'package:threedpass/core/polkawallet/non_native_tokens_api.dart'; import 'package:threedpass/core/polkawallet/utils/balance_utils.dart'; import 'package:threedpass/core/polkawallet/utils/network_state_data_extension.dart'; import 'package:threedpass/core/polkawallet/utils/transfer_type.dart'; +import 'package:threedpass/core/polkawallet/utils/tx_info.dart'; +import 'package:threedpass/features/wallet_screen/bloc/notifications_cubit.dart'; +import 'package:threedpass/features/wallet_screen/domain/entities/transfer.dart'; import 'package:threedpass/features/wallet_screen/domain/entities/transfer_meta_dto.dart'; +part 'meta_tx_infos_fabric.dart'; part 'transfer_info_bloc.g.dart'; part 'transfer_info_bloc_event.dart'; part 'transfer_info_bloc_state.dart'; @@ -31,19 +41,18 @@ class TransferInfoBloc ), ], fees: null, - transactionOption: TransferTypeValue.defaultType, + transactionOption: BalanceTransactionTypeValue.defaultType, amounts: [ SendAmountData( amountController: TextEditingController(), - balance: initialBalance(appService), ), ], ), ) { final initialAddress = initialFrom(appService).data!.address!; - final balance = initialBalance(appService); + final balance = initialBalance(appService, metaDTO); - balanceCache = { + balanceCacheNotifier.value = { initialAddress: balance, }; @@ -56,12 +65,26 @@ class TransferInfoBloc on(_removeToAddress); on(_copyPassword); } - static double initialBalance(final AppService appService) { - final rawAvaliable = - appService.chosenAccountBalance.value.availableBalance as String; - final decimals = appService.networkStateData.safeDecimals; - final res = BalanceUtils.balanceToDouble(rawAvaliable, decimals); - return res; + static double initialBalance( + final AppService appService, + final TransferMetaDTO metaDTO, + ) { + switch (metaDTO.type) { + case MetaInfoType.asset: + // appService.tokensAreLoading + final tbd = (metaDTO as AssetTransferMetaDTO).tokenBalanceData; + final amount = tbd.amount; + final decimals = tbd.decimals; + + return BalanceUtils.balanceToDouble(amount!, decimals!); + + case MetaInfoType.coin: + final rawAvaliable = + appService.chosenAccountBalance.value.availableBalance as String; + final decimals = appService.networkStateData.safeDecimals; + final res = BalanceUtils.balanceToDouble(rawAvaliable, decimals); + return res; + } } static FromAddressData initialFrom(final AppService appService) { @@ -79,7 +102,8 @@ class TransferInfoBloc final TransferMetaDTO metaDTO; final AppService appService; - late final Map balanceCache; + final ValueNotifier> balanceCacheNotifier = + ValueNotifier({}); Future init() async { // final txInfo = metaDTO.getTxInfo(state.type); @@ -121,31 +145,33 @@ class TransferInfoBloc required final BuildContext context, required final GlobalKey formKey, }) async { - // final txInfo = metaDTO.getTxInfo(state.type); - // final params = metaDTO.getParams( - // amount, - // toAddress, - // ); - - // final notificationsCubit = BlocProvider.of(context); - // final appServiceCubit = BlocProvider.of(context); - - // // print(metaDTO.getName()); - - // await Transfer( - // txInfo: txInfo, - // params: params, - // appService: appService, - // context: context, - // toAddress: toAddress, - // password: password, - // formKey: formKey, - // notificationsCubit: notificationsCubit, - // addHandler: appServiceCubit.addHandler, - // symbols: metaDTO.getName(), - // decimals: metaDTO.decimals, - // amountNotification: amount, - // ).sendFunds(); + try { + final notificationsCubit = BlocProvider.of(context); + final appServiceCubit = BlocProvider.of(context); + + final metaTxInfos = + _MetaTxInfosFabric(metaDTO: metaDTO, state: state).build(); + + // final txInfos = metaTxInfos.map((final e) => e.txInfo()).toList(); + // final params = metaTxInfos.map((final e) => e.params()).toList(); + final passwords = state.fromAddresses + .map((final e) => e.passwordController.text) + .toList(); + + await Transfer( + metaInfos: metaTxInfos, + appService: appService, + context: context, + passwords: passwords, + formKey: formKey, + notificationsCubit: notificationsCubit, + addHandler: appServiceCubit.addHandler, + symbols: metaDTO.name, + decimals: metaDTO.decimals, + ).sendFunds(); + } on Object catch (e) { + print(e); + } } void _updateTransferType( @@ -200,18 +226,42 @@ class TransferInfoBloc emit(state.copyWith(fromAddresses: newFromAddresses)); } - FutureOr getBalance(final String address) async { - if (balanceCache.containsKey(address)) { - return Future.value(balanceCache[address]!); + FutureOr updateBalance(final String address) async { + // final cache = Map.from(balanceCacheNotifier.value); + if (balanceCacheNotifier.value.containsKey(address)) { + return; } else { - final balanceData = - await appService.plugin.sdk.api.account.queryBalance(address); - final decimals = appService.networkStateData.safeDecimals; - final rawAvaliableBalance = balanceData!.availableBalance as String; - final balance = - BalanceUtils.balanceToDouble(rawAvaliableBalance, decimals); - balanceCache[address] = balance; - return balance; + switch (metaDTO.type) { + case MetaInfoType.asset: + // appService.tokensAreLoading + final nnta = NonNativeTokensApi(appService, address); + final tbd = await nnta.process(); + for (final t in tbd) { + if (t.id == (metaDTO as AssetTransferMetaDTO).tokenBalanceData.id) { + try { + final balance = + BalanceUtils.balanceToDouble(t.amount!, t.decimals!); + balanceCacheNotifier.value[address] = balance; + } on Object catch (e) { + print(e); + unawaited( + Fluttertoast.showToast( + msg: "Couldn't parse balance of token ${t.id} ${t.name}", + ), + ); + } + } + } + case MetaInfoType.coin: + final balanceData = + await appService.plugin.sdk.api.account.queryBalance(address); + final decimals = appService.networkStateData.safeDecimals; + final rawAvaliableBalance = balanceData!.availableBalance as String; + final balance = + BalanceUtils.balanceToDouble(rawAvaliableBalance, decimals); + balanceCacheNotifier.value[address] = balance; + } + balanceCacheNotifier.notifyListeners(); } } @@ -225,17 +275,37 @@ class TransferInfoBloc return; } - final balance = await getBalance(accAddress); - - // Some racing is possible - final newAmountsList = List.from(state.amounts); - final newFromAddresses = List.from(state.fromAddresses); - final indexOfCurrent = newFromAddresses.indexOf(event.fromAddressData); - - final oldAmount = newAmountsList[indexOfCurrent]; - final newAmount = oldAmount.copyWith(balance: balance); - newAmountsList.replace(oldAmount, newAmount); + await updateBalance(accAddress); + } +} - emit(state.copyWith(amounts: newAmountsList)); +/// 1 - SINGLE TRANSFER +/// 2 - FROM ONE TO MANY +/// 3 - FROM MANY TO ONE +Future caseSplit({ + required final List txInfos, + required final List params, + required final List passwords, + required final dynamic Function() onFirst, + required final dynamic Function() onSecond, + required final dynamic Function() onThird, + required final dynamic Function() onError, +}) async { + debugPrint( + 'caseSplit txInfosLen=${txInfos.length} paramsLen=${params.length} passwordsLen=${passwords.length}', + ); + if (txInfos.length == 1 && params.length == 1) { + // SINGLE TRANSFER + onFirst(); + } else if (txInfos.length == 1 && params.length > 1) { + // FROM ONE TO MANY + onSecond(); + } else if (txInfos.length > 1 && + params.length == 1 && + txInfos.length == passwords.length) { + // FROM MANY TO ONE + onThird(); + } else { + onError(); } } diff --git a/lib/features/wallet_screen/bloc/transfer_info_bloc.g.dart b/lib/features/wallet_screen/bloc/transfer_info_bloc.g.dart index 94f87812..cf507395 100644 --- a/lib/features/wallet_screen/bloc/transfer_info_bloc.g.dart +++ b/lib/features/wallet_screen/bloc/transfer_info_bloc.g.dart @@ -6,6 +6,110 @@ part of 'transfer_info_bloc.dart'; // CopyWithGenerator // ************************************************************************** +abstract class _$TransferInfoBlocStateCWProxy { + TransferInfoBlocState fromAddresses(List fromAddresses); + + TransferInfoBlocState toAddresses(List toAddresses); + + TransferInfoBlocState fees(TxFeeEstimateResult? fees); + + TransferInfoBlocState transactionOption( + BalanceTransactionType transactionOption); + + TransferInfoBlocState amounts(List amounts); + + /// This function **does support** nullification of nullable fields. All `null` values passed to `non-nullable` fields will be ignored. You can also use `TransferInfoBlocState(...).copyWith.fieldName(...)` to override fields one at a time with nullification support. + /// + /// Usage + /// ```dart + /// TransferInfoBlocState(...).copyWith(id: 12, name: "My name") + /// ```` + TransferInfoBlocState call({ + List? fromAddresses, + List? toAddresses, + TxFeeEstimateResult? fees, + BalanceTransactionType? transactionOption, + List? amounts, + }); +} + +/// Proxy class for `copyWith` functionality. This is a callable class and can be used as follows: `instanceOfTransferInfoBlocState.copyWith(...)`. Additionally contains functions for specific fields e.g. `instanceOfTransferInfoBlocState.copyWith.fieldName(...)` +class _$TransferInfoBlocStateCWProxyImpl + implements _$TransferInfoBlocStateCWProxy { + const _$TransferInfoBlocStateCWProxyImpl(this._value); + + final TransferInfoBlocState _value; + + @override + TransferInfoBlocState fromAddresses(List fromAddresses) => + this(fromAddresses: fromAddresses); + + @override + TransferInfoBlocState toAddresses(List toAddresses) => + this(toAddresses: toAddresses); + + @override + TransferInfoBlocState fees(TxFeeEstimateResult? fees) => this(fees: fees); + + @override + TransferInfoBlocState transactionOption( + BalanceTransactionType transactionOption) => + this(transactionOption: transactionOption); + + @override + TransferInfoBlocState amounts(List amounts) => + this(amounts: amounts); + + @override + + /// This function **does support** nullification of nullable fields. All `null` values passed to `non-nullable` fields will be ignored. You can also use `TransferInfoBlocState(...).copyWith.fieldName(...)` to override fields one at a time with nullification support. + /// + /// Usage + /// ```dart + /// TransferInfoBlocState(...).copyWith(id: 12, name: "My name") + /// ```` + TransferInfoBlocState call({ + Object? fromAddresses = const $CopyWithPlaceholder(), + Object? toAddresses = const $CopyWithPlaceholder(), + Object? fees = const $CopyWithPlaceholder(), + Object? transactionOption = const $CopyWithPlaceholder(), + Object? amounts = const $CopyWithPlaceholder(), + }) { + return TransferInfoBlocState( + fromAddresses: + fromAddresses == const $CopyWithPlaceholder() || fromAddresses == null + ? _value.fromAddresses + // ignore: cast_nullable_to_non_nullable + : fromAddresses as List, + toAddresses: + toAddresses == const $CopyWithPlaceholder() || toAddresses == null + ? _value.toAddresses + // ignore: cast_nullable_to_non_nullable + : toAddresses as List, + fees: fees == const $CopyWithPlaceholder() + ? _value.fees + // ignore: cast_nullable_to_non_nullable + : fees as TxFeeEstimateResult?, + transactionOption: transactionOption == const $CopyWithPlaceholder() || + transactionOption == null + ? _value.transactionOption + // ignore: cast_nullable_to_non_nullable + : transactionOption as BalanceTransactionType, + amounts: amounts == const $CopyWithPlaceholder() || amounts == null + ? _value.amounts + // ignore: cast_nullable_to_non_nullable + : amounts as List, + ); + } +} + +extension $TransferInfoBlocStateCopyWith on TransferInfoBlocState { + /// Returns a callable class that can be used as follows: `instanceOfTransferInfoBlocState.copyWith(...)` or like so:`instanceOfTransferInfoBlocState.copyWith.fieldName(...)`. + // ignore: library_private_types_in_public_api + _$TransferInfoBlocStateCWProxy get copyWith => + _$TransferInfoBlocStateCWProxyImpl(this); +} + abstract class _$FromAddressDataCWProxy { FromAddressData data(KeyPairData? data); @@ -125,8 +229,6 @@ extension $ToAddressDataCopyWith on ToAddressData { abstract class _$SendAmountDataCWProxy { SendAmountData amountController(TextEditingController amountController); - SendAmountData balance(double? balance); - /// This function **does support** nullification of nullable fields. All `null` values passed to `non-nullable` fields will be ignored. You can also use `SendAmountData(...).copyWith.fieldName(...)` to override fields one at a time with nullification support. /// /// Usage @@ -135,7 +237,6 @@ abstract class _$SendAmountDataCWProxy { /// ```` SendAmountData call({ TextEditingController? amountController, - double? balance, }); } @@ -149,9 +250,6 @@ class _$SendAmountDataCWProxyImpl implements _$SendAmountDataCWProxy { SendAmountData amountController(TextEditingController amountController) => this(amountController: amountController); - @override - SendAmountData balance(double? balance) => this(balance: balance); - @override /// This function **does support** nullification of nullable fields. All `null` values passed to `non-nullable` fields will be ignored. You can also use `SendAmountData(...).copyWith.fieldName(...)` to override fields one at a time with nullification support. @@ -162,7 +260,6 @@ class _$SendAmountDataCWProxyImpl implements _$SendAmountDataCWProxy { /// ```` SendAmountData call({ Object? amountController = const $CopyWithPlaceholder(), - Object? balance = const $CopyWithPlaceholder(), }) { return SendAmountData( amountController: amountController == const $CopyWithPlaceholder() || @@ -170,10 +267,6 @@ class _$SendAmountDataCWProxyImpl implements _$SendAmountDataCWProxy { ? _value.amountController // ignore: cast_nullable_to_non_nullable : amountController as TextEditingController, - balance: balance == const $CopyWithPlaceholder() - ? _value.balance - // ignore: cast_nullable_to_non_nullable - : balance as double?, ); } } @@ -183,106 +276,3 @@ extension $SendAmountDataCopyWith on SendAmountData { // ignore: library_private_types_in_public_api _$SendAmountDataCWProxy get copyWith => _$SendAmountDataCWProxyImpl(this); } - -abstract class _$TransferInfoBlocStateCWProxy { - TransferInfoBlocState fromAddresses(List fromAddresses); - - TransferInfoBlocState toAddresses(List toAddresses); - - TransferInfoBlocState fees(TxFeeEstimateResult? fees); - - TransferInfoBlocState transactionOption(TransactionOption transactionOption); - - TransferInfoBlocState amounts(List amounts); - - /// This function **does support** nullification of nullable fields. All `null` values passed to `non-nullable` fields will be ignored. You can also use `TransferInfoBlocState(...).copyWith.fieldName(...)` to override fields one at a time with nullification support. - /// - /// Usage - /// ```dart - /// TransferInfoBlocState(...).copyWith(id: 12, name: "My name") - /// ```` - TransferInfoBlocState call({ - List? fromAddresses, - List? toAddresses, - TxFeeEstimateResult? fees, - TransactionOption? transactionOption, - List? amounts, - }); -} - -/// Proxy class for `copyWith` functionality. This is a callable class and can be used as follows: `instanceOfTransferInfoBlocState.copyWith(...)`. Additionally contains functions for specific fields e.g. `instanceOfTransferInfoBlocState.copyWith.fieldName(...)` -class _$TransferInfoBlocStateCWProxyImpl - implements _$TransferInfoBlocStateCWProxy { - const _$TransferInfoBlocStateCWProxyImpl(this._value); - - final TransferInfoBlocState _value; - - @override - TransferInfoBlocState fromAddresses(List fromAddresses) => - this(fromAddresses: fromAddresses); - - @override - TransferInfoBlocState toAddresses(List toAddresses) => - this(toAddresses: toAddresses); - - @override - TransferInfoBlocState fees(TxFeeEstimateResult? fees) => this(fees: fees); - - @override - TransferInfoBlocState transactionOption( - TransactionOption transactionOption) => - this(transactionOption: transactionOption); - - @override - TransferInfoBlocState amounts(List amounts) => - this(amounts: amounts); - - @override - - /// This function **does support** nullification of nullable fields. All `null` values passed to `non-nullable` fields will be ignored. You can also use `TransferInfoBlocState(...).copyWith.fieldName(...)` to override fields one at a time with nullification support. - /// - /// Usage - /// ```dart - /// TransferInfoBlocState(...).copyWith(id: 12, name: "My name") - /// ```` - TransferInfoBlocState call({ - Object? fromAddresses = const $CopyWithPlaceholder(), - Object? toAddresses = const $CopyWithPlaceholder(), - Object? fees = const $CopyWithPlaceholder(), - Object? transactionOption = const $CopyWithPlaceholder(), - Object? amounts = const $CopyWithPlaceholder(), - }) { - return TransferInfoBlocState( - fromAddresses: - fromAddresses == const $CopyWithPlaceholder() || fromAddresses == null - ? _value.fromAddresses - // ignore: cast_nullable_to_non_nullable - : fromAddresses as List, - toAddresses: - toAddresses == const $CopyWithPlaceholder() || toAddresses == null - ? _value.toAddresses - // ignore: cast_nullable_to_non_nullable - : toAddresses as List, - fees: fees == const $CopyWithPlaceholder() - ? _value.fees - // ignore: cast_nullable_to_non_nullable - : fees as TxFeeEstimateResult?, - transactionOption: transactionOption == const $CopyWithPlaceholder() || - transactionOption == null - ? _value.transactionOption - // ignore: cast_nullable_to_non_nullable - : transactionOption as TransactionOption, - amounts: amounts == const $CopyWithPlaceholder() || amounts == null - ? _value.amounts - // ignore: cast_nullable_to_non_nullable - : amounts as List, - ); - } -} - -extension $TransferInfoBlocStateCopyWith on TransferInfoBlocState { - /// Returns a callable class that can be used as follows: `instanceOfTransferInfoBlocState.copyWith(...)` or like so:`instanceOfTransferInfoBlocState.copyWith.fieldName(...)`. - // ignore: library_private_types_in_public_api - _$TransferInfoBlocStateCWProxy get copyWith => - _$TransferInfoBlocStateCWProxyImpl(this); -} diff --git a/lib/features/wallet_screen/bloc/transfer_info_bloc_event.dart b/lib/features/wallet_screen/bloc/transfer_info_bloc_event.dart index ce26fa9b..7cbdd4bd 100644 --- a/lib/features/wallet_screen/bloc/transfer_info_bloc_event.dart +++ b/lib/features/wallet_screen/bloc/transfer_info_bloc_event.dart @@ -5,7 +5,7 @@ abstract class TransferInfoBlocEvent { } class UpdateTransferTypeEvent extends TransferInfoBlocEvent { - final TransactionOption value; + final BalanceTransactionType value; const UpdateTransferTypeEvent(this.value); } diff --git a/lib/features/wallet_screen/bloc/transfer_info_bloc_fields_events.dart b/lib/features/wallet_screen/bloc/transfer_info_bloc_fields_events.dart index edef04a0..3f15fc1e 100644 --- a/lib/features/wallet_screen/bloc/transfer_info_bloc_fields_events.dart +++ b/lib/features/wallet_screen/bloc/transfer_info_bloc_fields_events.dart @@ -17,7 +17,6 @@ extension FieldEvents on TransferInfoBloc { newAmountsList.add( SendAmountData( amountController: TextEditingController(), - balance: null, ), ); @@ -40,17 +39,10 @@ extension FieldEvents on TransferInfoBloc { ), ); - final firstAccAddress = state.fromAddresses.first.data!.address; - final firstAccBalance = balanceCache[firstAccAddress]; - - final newAmountsList = []; - for (final i in state.amounts) { - newAmountsList.add(i.copyWith(balance: firstAccBalance)); - } + final newAmountsList = List.from(state.amounts); newAmountsList.add( SendAmountData( amountController: TextEditingController(), - balance: firstAccBalance, ), ); diff --git a/lib/features/wallet_screen/bloc/transfer_info_bloc_state.dart b/lib/features/wallet_screen/bloc/transfer_info_bloc_state.dart index ff14827a..577331ca 100644 --- a/lib/features/wallet_screen/bloc/transfer_info_bloc_state.dart +++ b/lib/features/wallet_screen/bloc/transfer_info_bloc_state.dart @@ -5,7 +5,7 @@ class TransferInfoBlocState { // Max avaliable balance in wallet in human-readable double format // final double balance; final TxFeeEstimateResult? fees; - final TransactionOption transactionOption; + final BalanceTransactionType transactionOption; final List fromAddresses; final List toAddresses; final List amounts; @@ -50,9 +50,7 @@ class ToAddressData { class SendAmountData { const SendAmountData({ required this.amountController, - required this.balance, }); final TextEditingController amountController; - final double? balance; } diff --git a/lib/features/wallet_screen/domain/entities/multitransfer_atom.dart b/lib/features/wallet_screen/domain/entities/multitransfer_atom.dart deleted file mode 100644 index 4eb5a9fb..00000000 --- a/lib/features/wallet_screen/domain/entities/multitransfer_atom.dart +++ /dev/null @@ -1,61 +0,0 @@ -import 'package:polkawallet_sdk/api/types/txInfoData.dart'; -import 'package:polkawallet_sdk/storage/types/keyPairData.dart'; -import 'package:threedpass/core/polkawallet/utils/balance_utils.dart'; -import 'package:threedpass/core/polkawallet/utils/transfer_type.dart'; - -abstract class TransferTxInfoI { - final KeyPairData senderData; - final int decimals; - - const TransferTxInfoI({ - required this.decimals, - required this.senderData, - }); - - TxInfoData txInfo( - final TransactionOption transferType, - ); - List params(final String? amount, final String toAddress); -} - -class MultitransferAtomCoins extends TransferTxInfoI { - // txinfo - final String senderAddress; - final String senderPubKey; - final TransactionOption transferType; - final String module = 'balances'; - final int decimals; - - // params - final String toAddress; - final double amount; - - TxInfoData txInfo( - final TransactionOption transferType, - ) => - TxInfoData( - 'balances', - TransferTypeValue(transferType).toString(), - TxSenderData( - senderAddress, - senderPubKey, - ), - ); - - List params( - final String? amount, - final String toAddress, - ) { - final realAmount = BalanceUtils.tokenInt( - amount, - decimals, - ); - - return [ - // params.to - toAddress, - // params.amount - realAmount.toString(), - ]; - } -} diff --git a/lib/features/wallet_screen/domain/entities/transaction.dart b/lib/features/wallet_screen/domain/entities/transaction.dart new file mode 100644 index 00000000..8407597e --- /dev/null +++ b/lib/features/wallet_screen/domain/entities/transaction.dart @@ -0,0 +1,188 @@ +import 'dart:async'; + +import 'package:auto_route/auto_route.dart'; +import 'package:easy_localization/easy_localization.dart'; +import 'package:flutter/material.dart'; +import 'package:fluttertoast/fluttertoast.dart'; +import 'package:polkawallet_sdk/p3d/tx_info.dart'; +import 'package:threedpass/core/polkawallet/app_service.dart'; +import 'package:threedpass/core/widgets/default_loading_dialog.dart'; + +abstract class _Transaction { + const _Transaction({ + required this.addHandler, + required this.appService, + required this.context, + required this.finishNotificationWithError, + required this.globalContext, + }); + + final AppService appService; + final BuildContext context; + final BuildContext globalContext; + final void Function(Map, String> data) addHandler; + final void Function(String error) finishNotificationWithError; + + Future send() async { + try { + unawaited(useApi()); + // final b = 1 + 1; + // print('Finished'); + } on Object catch (e) { + try { + // DO NOT REMOVE THIS LINE + // It throws an error if old context doesn't exist. Otherwise it will + // close the dialog. + debugPrint('check if transfer dialog was closed'); + final ___ = context.router.stack; + // debugPrint('close transfer dialog'); + DefaultLoadingDialog.hide(globalContext); + // DIALOG WAS NOT CLOSED + } on Object catch (_) { + // DIALOG WAS CLOSED + debugPrint('transfer dialog was already closed'); + } + + finishNotificationWithError(e.toString()); + debugPrint(e.toString()); + // unawaited(Fluttertoast.showToast(msg: e.toString())); + } + + try { + // DO NOT REMOVE THIS LINE + // It throws an error if old context doesn't exist. Otherwise it will + // close the dialog. + debugPrint('FINISH TRANSFER SCREEN. check if transfer dialog was closed'); + final ___ = context.router.stack; + // debugPrint('close transfer dialog'); + DefaultLoadingDialog.hide(globalContext); + + // DIALOG WAS NOT CLOSED + } on Object catch (_) { + // DIALOG WAS CLOSED + debugPrint('FINISH TRANSFER SCREEN. transfer dialog was already closed'); + } + + try { + unawaited(context.router.pop()); + } on Object catch (_) { + // DIALOG WAS CLOSED + debugPrint('FINISH TRANSFER SCREEN. Catch. context.router.pop();'); + } + } + + Future useApi(); + + void onStatusChange(final String p0) { + // There are two calls of this callback: p0 == 'Ready' and p0 == 'Broadcast' + // print(p0 + ' ' + params.toString()); + // switch (p0) { + // case 'Ready': + // debugPrint('Got ready status'); + // try { + // // DO NOT REMOVE THIS LINE + // // It throws an error if old context doesn't exist. Otherwise it will + // // close the dialog. + // debugPrint('Check if already got ready status'); + // final ___ = context.router.stack; + // DefaultLoadingDialog.hide(globalContext); + // context.router.pop(); + // Fluttertoast.showToast(msg: 'transfer_success_text'.tr()); + // // DIALOG WAS NOT CLOSED + // } on Object catch (_) { + // // DIALOG WAS CLOSED + // debugPrint('Ready status was already got somewhere'); + // } + // break; + + // case 'Broadcast': + // debugPrint('Broadcast'); + + // default: + // debugPrint(p0); + // } + } + + void msgIdCallback(final Map, String> data) { + // debugPrint('SET MSG ID $msgId'); + addHandler(data); + } +} + +class SingleTransaction extends _Transaction { + const SingleTransaction({ + required super.addHandler, + required super.appService, + required super.context, + required super.finishNotificationWithError, + required super.globalContext, + required this.password, + required this.txInfoMeta, + }) : super(); + + final TransferTxInfoI txInfoMeta; + final String password; + + @override + Future useApi() async { + final d1 = await appService.plugin.sdk.api.tx.signAndSend( + txInfo: txInfoMeta, + password: password, + onStatusChange: onStatusChange, + msgIdCallback: msgIdCallback, + ); + print(d1); + } +} + +class MultiTxSingleSender extends _Transaction { + const MultiTxSingleSender({ + required super.addHandler, + required super.appService, + required super.context, + required super.finishNotificationWithError, + required super.globalContext, + required this.txInfoMetas, + required this.password, + }) : super(); + + final List txInfoMetas; + final String password; + + @override + Future useApi() async { + final d1 = await appService.plugin.sdk.api.tx.sendMultiTxSingleSender( + txInfoMetas: txInfoMetas, + password: password, + onStatusChange: onStatusChange, + msgIdCallback: msgIdCallback, + ); + print(d1); + } +} + +class MultiTxMultiSender extends _Transaction { + const MultiTxMultiSender({ + required super.addHandler, + required super.appService, + required super.context, + required super.finishNotificationWithError, + required super.globalContext, + required this.passwords, + required this.txInfoMetas, + }) : super(); + + final List txInfoMetas; + final List passwords; + + @override + Future useApi() async { + final d1 = await appService.plugin.sdk.api.tx.sendMultiTxMultiSender( + txInfoMetas: txInfoMetas, + passwords: passwords, + onStatusChange: onStatusChange, + msgIdCallback: msgIdCallback, + ); + print(d1); + } +} diff --git a/lib/features/wallet_screen/domain/entities/transfer.dart b/lib/features/wallet_screen/domain/entities/transfer.dart index d607fbfc..2a846ecf 100644 --- a/lib/features/wallet_screen/domain/entities/transfer.dart +++ b/lib/features/wallet_screen/domain/entities/transfer.dart @@ -1,51 +1,52 @@ import 'dart:async'; -import 'package:auto_route/auto_route.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:fluttertoast/fluttertoast.dart'; import 'package:polkawallet_sdk/api/types/txInfoData.dart'; +import 'package:polkawallet_sdk/p3d/tx_info.dart'; +import 'package:polkawallet_sdk/p3d/tx_params.dart'; import 'package:threedpass/core/polkawallet/app_service.dart'; import 'package:threedpass/core/polkawallet/utils/tx_update_event_logs_handler.dart'; import 'package:threedpass/core/widgets/default_loading_dialog.dart'; import 'package:threedpass/features/home_page/bloc/home_context_cubit.dart'; import 'package:threedpass/features/wallet_screen/bloc/notifications_cubit.dart'; +import 'package:threedpass/features/wallet_screen/bloc/transfer_info_bloc.dart'; +import 'package:threedpass/features/wallet_screen/domain/entities/transaction.dart'; import 'package:threedpass/features/wallet_screen/domain/entities/transfer_history_ui.dart'; class Transfer { Transfer({ - required this.txInfo, - required this.params, + // required this.params, required this.appService, required this.context, required this.formKey, - required this.password, - required this.toAddress, required this.notificationsCubit, required this.addHandler, required this.symbols, required this.decimals, - required this.amountNotification, + // required this.amounts, + required this.passwords, + required this.metaInfos, + // required this.txInfos, }); // final String amount; final AppService appService; - final TxInfoData txInfo; - final List params; + final List metaInfos; + // final List txInfos; + // final List params; final BuildContext context; final GlobalKey formKey; - final String password; - final String toAddress; + final List passwords; final NotificationsCubit notificationsCubit; - final void Function(String, void Function(String)) addHandler; + final void Function(String, TransactionsCallback) addHandler; final String symbols; final int decimals; - final String amountNotification; + // final List amounts; - bool isFinished = false; - - Future checkAddressAndNotify() async { + Future checkAddressAndNotify(final String toAddress) async { final addressCorrect = await appService.plugin.sdk.api.account.checkAddressFormat( toAddress, @@ -65,109 +66,174 @@ class Transfer { return true; } + Future checkAllAddresses(final List params) async { + for (final p in params) { + if (!await checkAddressAndNotify(p.toAddress)) { + return false; + } + } + + return true; + } + Future sendFunds() async { if (formKey.currentState!.validate()) { - final addressCorrect = await checkAddressAndNotify(); + final params = metaInfos.map((final e) => e.params()).toList(); + final addressCorrect = await checkAllAddresses(params); if (!addressCorrect) { return; } + final fromAddress = + metaInfos.map((final e) => e.txInfo().sender!.address!).toList(); + final uniqueFromAddresses = Set.from(fromAddress).toList(); + + if (uniqueFromAddresses.length != passwords.length) { + debugPrint( + 'params.length != txInfos.length || txInfos.length != passwords.length', + ); + return; + } + + final toAddresses = params.map((final e) => e.toAddress).toList(); + final uniqueToAddresses = Set.from(toAddresses).toList(); + + final amounts = params + .map((final e) => e.amount) + .map((final e) => e.toString()) + .toList(); + final globalContext = BlocProvider.of(context).state.context; DefaultLoadingDialog.show(globalContext, 'transfer_loader_text'.tr()); - final tmpN = NotificationDTO( - type: NotificationType.transfer, - status: ExtrisincStatus.loading, - toAddresses: [toAddress], - fromAddresses: [txInfo.sender?.address ?? ''], - amount: - amountNotification, //BalanceUtils.balanceToDouble(params[1], decimals).toString(), - symbols: symbols, - blockDateTime: null, - ); - // int i = 0; - - notificationsCubit.add(tmpN); - - try { - final d1 = await appService.plugin.sdk.api.tx.signAndSend( - txInfo, - params, - password, - onStatusChange: (final p0) { - // There are two calls of this callback: p0 == 'Ready' and p0 == 'Broadcast' - // print(p0 + ' ' + params.toString()); - switch (p0) { - case 'Ready': - // final readN = tmpN.copyWith(status: TransactionStatus.pending,); - // notificationsCubit.replace(tmpN, readN); - // tmpN = readN; - - DefaultLoadingDialog.hide(globalContext); - context.router.pop(); - Fluttertoast.showToast(msg: 'transfer_success_text'.tr()); - break; - - case 'Broadcast': - // i++; - - // final readN = tmpN.copyWith(status:TransactionStatus.pending,); - // notificationsCubit.replace(tmpN, readN); - // tmpN = readN; - - debugPrint('Broadcast'); - - default: - debugPrint(p0); - } - }, - msgIdCallback: (final String msgId) { - debugPrint('SET MSG ID $msgId'); - addHandler( - msgId, - (final String p0) { - isFinished = true; - final finishedTransaction = tmpN.copyWith( - status: p0 == TxUpdateEventLogsHandler.extrinsicSuccess - ? ExtrisincStatus.success - : ExtrisincStatus.failed, - message: p0, - blockDateTime: DateTime.now().toUtc(), - ); - notificationsCubit.replace(tmpN, finishedTransaction); - }, - ); - }, + final notifications = []; + + for (int i = 0; i < metaInfos.length; i++) { + notifications.add( + NotificationDTO( + type: NotificationType.transfer, + status: ExtrisincStatus.loading, + toAddress: toAddresses[i], + fromAddress: fromAddress[i], + amount: amounts[i], + symbols: symbols, + blockDateTime: null, + ), ); - // final b = 1 + 1; - // print('Finished'); - } on Object catch (e) { - // print('aaaaaaaaaaaa'); - // final a = globalContext.router.stack; - - try { - final ___ = context.router.stack; - DefaultLoadingDialog.hide(globalContext); - // DIALOG WAS NOT CLOSED - } on Object catch (_) { - // DIALOG WAS CLOSED - debugPrint('dialog was closed'); - } + } - if (!isFinished) { - final finishedTransaction = tmpN.copyWith( - status: ExtrisincStatus.error, - message: e.toString(), - blockDateTime: DateTime.now().toUtc(), + final addHandlerV = (final Map, String> data) { + for (final k in data.keys) { + final msgId = data[k]!; + debugPrint('Add handler for $msgId'); + + addHandler( + msgId, + ({ + required final ExtrisincStatus status, + required final String? message, + }) { + // isFinished = true; + // TODO Send events to notifications bloc + final tmp = notifications.firstWhere( + (final element) => + element.fromAddress == k.first && + element.toAddress == k.last, + ); + + final finishedTransaction = tmp.copyWith( + status: status, + message: message, + blockDateTime: DateTime.now().toUtc(), + ); + notificationsCubit.replace( + tmp, + finishedTransaction, + ); + }, ); - notificationsCubit.replace(tmpN, finishedTransaction); } - - unawaited(Fluttertoast.showToast(msg: e.toString())); - } + }; + + final finishNotificationWithErrorV = (final String e) { + //if (!isFinished) { + // final tmp = notifications.firstWhere( + // (final element) => + // element.fromAddress == k.first && + // element.toAddress == k.last, + // ); + // final finishedTransaction = notifications.first.copyWith( + // status: ExtrisincStatus.error, + // message: e, + // blockDateTime: DateTime.now().toUtc(), + // ); + // notificationsCubit.replace(notifications.first, finishedTransaction); + //} + }; + + await caseSplit( + txInfos: uniqueFromAddresses, + params: uniqueToAddresses, + passwords: passwords, + onFirst: () async { + notifications.forEach((final element) { + notificationsCubit.add(element); + }); + debugPrint('SingleTransaction'); + unawaited(SingleTransaction( + addHandler: addHandlerV, + appService: appService, + context: context, + finishNotificationWithError: finishNotificationWithErrorV, + globalContext: globalContext, + password: passwords.first, + txInfoMeta: metaInfos.first, + ).send()); + }, + onSecond: () async { + notifications.forEach((final element) { + notificationsCubit.add(element); + }); + debugPrint('MultiTxSingleSender'); + unawaited(MultiTxSingleSender( + addHandler: addHandlerV, + appService: appService, + context: context, + finishNotificationWithError: finishNotificationWithErrorV, + globalContext: globalContext, + // params: params.map((final e) => e.paramsToSend()).toList(), + password: passwords.first, + txInfoMetas: metaInfos, + ).send()); + }, + onThird: () async { + notifications.forEach((final element) { + notificationsCubit.add(element); + }); + debugPrint('MultiTxMultiSender'); + unawaited(MultiTxMultiSender( + addHandler: addHandlerV, + appService: appService, + context: context, + finishNotificationWithError: finishNotificationWithErrorV, + globalContext: globalContext, + // txInfos: txInfos, + // params: params.map((final e) => e.paramsToSend()).toList(), + txInfoMetas: metaInfos, + passwords: passwords, + ).send()); + }, + onError: () async { + debugPrint('Transfer case split Error'); + DefaultLoadingDialog.hide(globalContext); + unawaited( + Fluttertoast.showToast(msg: 'Transfer error when case split.'), + ); + }, + ); } } } diff --git a/lib/features/wallet_screen/domain/entities/transfer_meta_dto.dart b/lib/features/wallet_screen/domain/entities/transfer_meta_dto.dart index bf02dd73..51e9f55c 100644 --- a/lib/features/wallet_screen/domain/entities/transfer_meta_dto.dart +++ b/lib/features/wallet_screen/domain/entities/transfer_meta_dto.dart @@ -1,47 +1,35 @@ -import 'package:polkawallet_sdk/api/types/txInfoData.dart'; import 'package:polkawallet_sdk/plugin/store/balances.dart'; -import 'package:threedpass/core/polkawallet/app_service.dart'; -import 'package:threedpass/core/polkawallet/utils/balance_utils.dart'; -import 'package:threedpass/core/polkawallet/utils/network_state_data_extension.dart'; -import 'package:threedpass/core/polkawallet/utils/transfer_type.dart'; -import 'package:threedpass/core/polkawallet/utils/tx_info.dart'; abstract class TransferMetaDTO { - const TransferMetaDTO(); - MetaInfoType get type; - String get name; - // TxInfoData getTxInfo(final TransferType transferType); + const TransferMetaDTO({ + required this.decimals, + required this.name, + }); - // List getParams( - // final String? amount, - // final String toAddress, - // ); + final int decimals; + final String name; - // int get decimals; + MetaInfoType get type; } class CoinsTransferMetaDTO extends TransferMetaDTO { const CoinsTransferMetaDTO({ - required this.name, + required super.name, + required super.decimals, }); - @override - final String name; - @override final MetaInfoType type = MetaInfoType.coin; } class AssetTransferMetaDTO extends TransferMetaDTO { const AssetTransferMetaDTO({ - required this.name, - required this.tokenId, + required super.name, + required super.decimals, + required this.tokenBalanceData, }); - final int tokenId; - - @override - final String name; + final TokenBalanceData tokenBalanceData; @override final MetaInfoType type = MetaInfoType.asset; diff --git a/lib/features/wallet_screen/presentation/assets_page/widgets/coin_transfer_button.dart b/lib/features/wallet_screen/presentation/assets_page/widgets/coin_transfer_button.dart index 3b5b0b07..61a0abbb 100644 --- a/lib/features/wallet_screen/presentation/assets_page/widgets/coin_transfer_button.dart +++ b/lib/features/wallet_screen/presentation/assets_page/widgets/coin_transfer_button.dart @@ -2,6 +2,7 @@ import 'package:auto_route/auto_route.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:threedpass/core/polkawallet/bloc/app_service_cubit.dart'; +import 'package:threedpass/core/polkawallet/utils/network_state_data_extension.dart'; import 'package:threedpass/core/widgets/buttons/floating_action_button.dart'; import 'package:threedpass/features/wallet_screen/domain/entities/transfer_meta_dto.dart'; import 'package:threedpass/features/wallet_screen/presentation/widgets/is_account_ready_builder.dart'; @@ -17,6 +18,7 @@ class CoinTransferButton extends StatelessWidget { TransferRouteWrapper( metadata: CoinsTransferMetaDTO( name: appService.networkStateData.tokenSymbol?.first ?? '', + decimals: appService.networkStateData.safeDecimals, ), ), ); diff --git a/lib/features/wallet_screen/presentation/assets_page/widgets/non_native_tokens/non_native_tokens.dart b/lib/features/wallet_screen/presentation/assets_page/widgets/non_native_tokens/non_native_tokens.dart index 3d29130f..ba4717c7 100644 --- a/lib/features/wallet_screen/presentation/assets_page/widgets/non_native_tokens/non_native_tokens.dart +++ b/lib/features/wallet_screen/presentation/assets_page/widgets/non_native_tokens/non_native_tokens.dart @@ -2,9 +2,11 @@ import 'package:auto_route/auto_route.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_platform_widgets/flutter_platform_widgets.dart'; +import 'package:polkawallet_sdk/api/types/balanceData.dart'; import 'package:polkawallet_sdk/plugin/store/balances.dart'; import 'package:threedpass/core/polkawallet/app_service.dart'; import 'package:threedpass/core/polkawallet/bloc/app_service_cubit.dart'; +import 'package:threedpass/core/polkawallet/utils/balance_utils.dart'; import 'package:threedpass/core/polkawallet/utils/network_state_data_extension.dart'; import 'package:threedpass/core/polkawallet/utils/token_balance_data_amount_check.dart'; import 'package:threedpass/core/widgets/d3p_card.dart'; @@ -38,31 +40,42 @@ class NonNativeTokens extends StatelessWidget { return const _AssetsLoading(); } - /// Subscribe to balance to update widget after transfer + // This builder checks if new account just immported and hides the assets + // until balance loads return ValueListenableBuilder( - valueListenable: appService.tokensAreLoading, - builder: (final context, final bool isLoading, final child) { - if (isLoading) { - return const _AssetsLoadingPlaceholder(); + valueListenable: appService.chosenAccountBalance, + builder: (final context, final BalanceData balance, final child) { + if (balance.isNull) { + return const SizedBox(); } - bool allTokensEmpty = true; - final tokensData = appService.plugin.balances.tokens; - for (final token in tokensData) { - if (token.isAmountPositive) { - allTokensEmpty = false; - } - } + /// Subscribe to balance to update widget after transfer + return ValueListenableBuilder( + valueListenable: appService.tokensAreLoading, + builder: (final context, final bool isLoading, final child) { + if (isLoading) { + return const _AssetsLoadingPlaceholder(); + } - final settings = - BlocProvider.of(context).state; - final showZeroAssets = settings.appSettings.showZeroAssets; + bool allTokensEmpty = true; + final tokensData = appService.plugin.balances.tokens; + for (final token in tokensData) { + if (token.isAmountPositive) { + allTokensEmpty = false; + } + } - if (allTokensEmpty && !showZeroAssets) { - return const _AssetsPlaceholder(); - } else { - return _AssetsColumn(tokensData); - } + final settings = + BlocProvider.of(context).state; + final showZeroAssets = settings.appSettings.showZeroAssets; + + if (allTokensEmpty && !showZeroAssets) { + return const _AssetsPlaceholder(); + } else { + return _AssetsColumn(tokensData); + } + }, + ); }, ); }, diff --git a/lib/features/wallet_screen/presentation/non_native_token_screen/presentation/widgets/asset_transfer_button.dart b/lib/features/wallet_screen/presentation/non_native_token_screen/presentation/widgets/asset_transfer_button.dart index 4de3e4f9..1626dc1d 100644 --- a/lib/features/wallet_screen/presentation/non_native_token_screen/presentation/widgets/asset_transfer_button.dart +++ b/lib/features/wallet_screen/presentation/non_native_token_screen/presentation/widgets/asset_transfer_button.dart @@ -2,7 +2,6 @@ import 'package:auto_route/auto_route.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; -import 'package:fluttertoast/fluttertoast.dart'; import 'package:threedpass/core/widgets/buttons/elevated_button.dart'; import 'package:threedpass/features/wallet_screen/domain/entities/transfer_meta_dto.dart'; import 'package:threedpass/features/wallet_screen/presentation/non_native_token_screen/bloc/assets_get_extrisincs_cubit.dart'; @@ -15,19 +14,15 @@ class AssetTransferButton extends StatelessWidget { final tkd = BlocProvider.of(context).tokenBalanceData; - try { - context.router.push( - TransferRouteWrapper( - metadata: AssetTransferMetaDTO( - tokenId: int.parse(tkd.id!), - name: tkd.name ?? '', - ), + context.router.push( + TransferRouteWrapper( + metadata: AssetTransferMetaDTO( + tokenBalanceData: tkd, + name: tkd.name ?? '', + decimals: tkd.decimals ?? 0, ), - ); - } on Exception catch (e) { - Fluttertoast.showToast( - msg: "Can't open transfer screen, because $e"); // TODO TRANSLATE - } + ), + ); } @override diff --git a/lib/features/wallet_screen/presentation/notifications_page/widgets/notifcation_transfer.dart b/lib/features/wallet_screen/presentation/notifications_page/widgets/notifcation_transfer.dart index 601916b2..5f01678b 100644 --- a/lib/features/wallet_screen/presentation/notifications_page/widgets/notifcation_transfer.dart +++ b/lib/features/wallet_screen/presentation/notifications_page/widgets/notifcation_transfer.dart @@ -40,18 +40,12 @@ class NotificationTransferCard extends StatelessWidget { ), const SizedBoxH4(), _Message(notificationDTO.message, notificationDTO.status), - TransactionItem( - object: TransferHistoryUI( - amount: notificationDTO.amount ?? 'error amount', - decimals: 1, - symbols: notificationDTO.symbols ?? 'error symbol', - direction: TransferDirection - .all, // Transfers are always "from", but from different accounts - blockDateTime: notificationDTO.blockDateTime, - fromAddress: notificationDTO.fromAddresses!.first, - toAddress: notificationDTO.toAddresses!.first, - extrisincStatus: null, - ), + _Transaction( + fromAddress: notificationDTO.fromAddress, + toAddress: notificationDTO.toAddress, + amount: notificationDTO.amount, + symbols: notificationDTO.symbols, + blockDateTime: notificationDTO.blockDateTime, ), ], ), @@ -62,6 +56,52 @@ class NotificationTransferCard extends StatelessWidget { } } +class _Transaction extends StatelessWidget { + const _Transaction({ + required this.amount, + required this.fromAddress, + required this.toAddress, + required this.blockDateTime, + required this.symbols, + }); + + final String? fromAddress; + final String? toAddress; + final String? amount; + final String? symbols; + final DateTime? blockDateTime; + + @override + Widget build(final BuildContext context) { + if (fromAddress != null && toAddress != null && amount != null) { + // return ListView.separated( + // physics: const NeverScrollableScrollPhysics(), + // padding: EdgeInsets.zero, + // shrinkWrap: true, + // itemCount: fromAddresses!.length, + // separatorBuilder: (final context, final index) => const Divider(), + // itemBuilder: (final context, final int index) { + return TransactionItem( + object: TransferHistoryUI( + amount: amount!, + decimals: 1, + symbols: symbols ?? '', + direction: TransferDirection + .all, // Transfers are always "from", but from different accounts + blockDateTime: blockDateTime, + fromAddress: fromAddress!, + toAddress: toAddress!, + extrisincStatus: null, + ), + ); + // }, + // ); + } else { + return const SizedBox(); + } + } +} + class _TransferStatus extends StatelessWidget { const _TransferStatus(this.status); diff --git a/lib/features/wallet_screen/presentation/transfer_page/widgets/add_card_basic.dart b/lib/features/wallet_screen/presentation/transfer_page/widgets/add_card_basic.dart index c860ace7..9d9bd414 100644 --- a/lib/features/wallet_screen/presentation/transfer_page/widgets/add_card_basic.dart +++ b/lib/features/wallet_screen/presentation/transfer_page/widgets/add_card_basic.dart @@ -1,7 +1,8 @@ -import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:threedpass/core/theme/d3p_special_colors.dart'; import 'package:threedpass/core/theme/d3p_special_styles.dart'; +import 'package:threedpass/core/widgets/buttons/elevated_button.dart'; import 'package:threedpass/core/widgets/buttons/icon_button.dart'; import 'package:threedpass/features/wallet_screen/bloc/transfer_info_bloc.dart'; @@ -19,41 +20,42 @@ class AddCardRowBasic extends StatelessWidget { @override Widget build(final BuildContext context) { - final textStyles = Theme.of(context).customTextStyles; - return BlocBuilder( - builder: (final context, final state) { - if (condition(state)) { - return Padding( - padding: const EdgeInsets.symmetric(vertical: 8), - child: Row( - children: [ - const Flexible( - flex: 1, - child: SizedBox( - width: double.infinity, - ), + final textStyle = Theme.of(context).customTextStyles; + final colors = Theme.of(context).customColors; + return Padding( + padding: const EdgeInsets.symmetric(horizontal: 8), + child: BlocBuilder( + builder: (final context, final state) { + if (condition(state)) { + return SizedBox( + height: 43, + child: D3pElevatedButton( + text: null, + onPressed: onPressed, + backgroundColor: colors.cardBackground, + elevation: 0, + childAlignment: MainAxisAlignment.start, + textStyle: textStyle.d3pBodyMedium, + shape: const RoundedRectangleBorder( + borderRadius: BorderRadius.all(Radius.circular(8)), ), - const SizedBox(width: 8), - D3pIconButton( - iconData: Icons.add_circle_outline_rounded, - onPressed: () => onPressed(), - emptyContraints: true, + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + D3pIconButton( + iconData: Icons.add_circle_outline_rounded, + onPressed: () => onPressed(), + emptyContraints: true, + ), + ], ), - const SizedBox(width: 8), - Flexible( - flex: 1, - child: Text( - unlocalizedText.tr(), - style: textStyles.hintStyle, - ), - ), - ], - ), - ); - } else { - return const SizedBox(); - } - }, + ), + ); + } else { + return const SizedBox(); + } + }, + ), ); } } diff --git a/lib/features/wallet_screen/presentation/transfer_page/widgets/add_to_card_row.dart b/lib/features/wallet_screen/presentation/transfer_page/widgets/add_to_card_row.dart index d60b92da..df85d3c0 100644 --- a/lib/features/wallet_screen/presentation/transfer_page/widgets/add_to_card_row.dart +++ b/lib/features/wallet_screen/presentation/transfer_page/widgets/add_to_card_row.dart @@ -10,13 +10,15 @@ class AddToCardRow extends StatelessWidget { @override Widget build(final BuildContext context) { - final transferInfoBloc = BlocProvider.of(context); - return AddCardRowBasic( - onPressed: () => transferInfoBloc.add(const AddToAddressEvent()), - unlocalizedText: 'add_account_to_label', - condition: (final state) => - state.screenType == TransferScreenType.one_to_many || - state.fromAddresses.length == 1, - ); + return const SizedBox(); + // TODO Turn on when utility palett will be added + // final transferInfoBloc = BlocProvider.of(context); + // return AddCardRowBasic( + // onPressed: () => transferInfoBloc.add(const AddToAddressEvent()), + // unlocalizedText: 'add_account_to_label', + // condition: (final state) => + // state.screenType == TransferScreenType.one_to_many || + // state.fromAddresses.length == 1, + // ); } } diff --git a/lib/features/wallet_screen/presentation/transfer_page/widgets/amount_textfield.dart b/lib/features/wallet_screen/presentation/transfer_page/widgets/amount_textfield.dart index cde5f812..37e49c51 100644 --- a/lib/features/wallet_screen/presentation/transfer_page/widgets/amount_textfield.dart +++ b/lib/features/wallet_screen/presentation/transfer_page/widgets/amount_textfield.dart @@ -1,6 +1,8 @@ import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:threedpass/core/polkawallet/utils/balance_utils.dart'; +import 'package:threedpass/features/wallet_screen/bloc/transfer_info_bloc.dart'; import 'package:threedpass/features/wallet_screen/domain/entities/transfer_meta_dto.dart'; import 'package:threedpass/features/wallet_screen/presentation/transfer_page/widgets/basic_transfer_textfield.dart'; @@ -8,20 +10,36 @@ class AmountTextFieldBuilder extends StatelessWidget { const AmountTextFieldBuilder({ required this.amountController, required this.transferType, - required this.balance, + required this.address, final Key? key, }) : super(key: key); final TextEditingController amountController; final MetaInfoType transferType; - final double balance; + final String address; @override Widget build(final BuildContext context) { - return _AmountTextField( - amountController: amountController, - balance: balance, - transferType: transferType, + final bloc = BlocProvider.of(context); + return ValueListenableBuilder( + valueListenable: bloc.balanceCacheNotifier, + builder: (final context, final value, final ___) { + if (value.containsKey(address)) { + return _AmountTextField( + amountController: amountController, + balance: value[address]!, + transferType: transferType, + enabled: true, + ); + } else { + return _AmountTextField( + amountController: amountController, + balance: 0, + transferType: transferType, + enabled: false, + ); + } + }, ); } } @@ -31,12 +49,14 @@ class _AmountTextField extends StatelessWidget { required this.amountController, required this.balance, required this.transferType, + required this.enabled, final Key? key, }) : super(key: key); final TextEditingController amountController; final MetaInfoType transferType; final double balance; + final bool enabled; String? Function(String? v) validator() { switch (transferType) { @@ -59,6 +79,7 @@ class _AmountTextField extends StatelessWidget { hintText: 'amount_hint'.tr(), validator: validator(), keyboardType: TextInputType.number, + enabled: enabled, ); } } diff --git a/lib/features/wallet_screen/presentation/transfer_page/widgets/from_address_textfield.dart b/lib/features/wallet_screen/presentation/transfer_page/widgets/from_address_textfield.dart index 4aa4199a..9f5ccfa9 100644 --- a/lib/features/wallet_screen/presentation/transfer_page/widgets/from_address_textfield.dart +++ b/lib/features/wallet_screen/presentation/transfer_page/widgets/from_address_textfield.dart @@ -182,6 +182,7 @@ class _AccountChooseTileText extends StatelessWidget { return Text.rich( TextSpan( text: fixedName(), + style: textStyles.d3pBodyMedium, children: [ TextSpan( text: shortAddress(), diff --git a/lib/features/wallet_screen/presentation/transfer_page/widgets/from_card_many_to_one.dart b/lib/features/wallet_screen/presentation/transfer_page/widgets/from_card_many_to_one.dart index ee4403fe..ff1271a0 100644 --- a/lib/features/wallet_screen/presentation/transfer_page/widgets/from_card_many_to_one.dart +++ b/lib/features/wallet_screen/presentation/transfer_page/widgets/from_card_many_to_one.dart @@ -38,7 +38,7 @@ class FromCardManyToOne extends StatelessWidget { AmountTextFieldBuilder( amountController: sendAmountData.amountController, transferType: metaInfoType, - balance: sendAmountData.balance ?? 0, + address: data.data?.address ?? '', ), ], ), diff --git a/lib/features/wallet_screen/presentation/transfer_page/widgets/to_card_one_to_many.dart b/lib/features/wallet_screen/presentation/transfer_page/widgets/to_card_one_to_many.dart index 3d319880..10ce071e 100644 --- a/lib/features/wallet_screen/presentation/transfer_page/widgets/to_card_one_to_many.dart +++ b/lib/features/wallet_screen/presentation/transfer_page/widgets/to_card_one_to_many.dart @@ -1,4 +1,5 @@ import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:threedpass/core/widgets/paddings.dart'; import 'package:threedpass/features/wallet_screen/bloc/transfer_info_bloc.dart'; import 'package:threedpass/features/wallet_screen/domain/entities/transfer_meta_dto.dart'; @@ -25,6 +26,7 @@ class ToCardOneToMany extends StatelessWidget { Widget build(final BuildContext context) { final dismissFunctionFabric = DismissFunctionFabric(context); final dismiss = isFirst ? null : dismissFunctionFabric.buildToAddress(data); + final bloc = BlocProvider.of(context); return BasicTransferBlock( dismiss: dismiss, child: Column( @@ -36,7 +38,7 @@ class ToCardOneToMany extends StatelessWidget { AmountTextFieldBuilder( amountController: sendAmountData.amountController, transferType: metaInfoType, - balance: sendAmountData.balance ?? 0, + address: bloc.state.fromAddresses.first.data?.address ?? '', ), ], ), diff --git a/lib/features/wallet_screen/presentation/transfer_page/widgets/transfer_type_switch.dart b/lib/features/wallet_screen/presentation/transfer_page/widgets/transfer_type_switch.dart index d92dc011..56fa4652 100644 --- a/lib/features/wallet_screen/presentation/transfer_page/widgets/transfer_type_switch.dart +++ b/lib/features/wallet_screen/presentation/transfer_page/widgets/transfer_type_switch.dart @@ -1,7 +1,7 @@ import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; -import 'package:threedpass/core/polkawallet/utils/transfer_type.dart'; +import 'package:polkawallet_sdk/p3d/balance_transaction_type.dart'; import 'package:threedpass/core/widgets/input/switch_button.dart'; import 'package:threedpass/features/wallet_screen/bloc/transfer_info_bloc.dart'; @@ -10,7 +10,10 @@ class TransferTypeSwitch extends StatelessWidget { final Key? key, }) : super(key: key); - void onChanged(final BuildContext context, final TransactionOption? value) { + void onChanged( + final BuildContext context, + final BalanceTransactionType? value, + ) { if (value != null) { BlocProvider.of(context) .add(UpdateTransferTypeEvent(value)); @@ -21,7 +24,7 @@ class TransferTypeSwitch extends StatelessWidget { Widget build(final BuildContext context) { final initialValue = BlocProvider.of(context).state.transactionOption == - TransactionOption.transferKeepAlive; + BalanceTransactionType.transferKeepAlive; return Padding( padding: const EdgeInsets.symmetric(horizontal: 8), child: D3pSwitchButton( @@ -30,8 +33,8 @@ class TransferTypeSwitch extends StatelessWidget { onChanged: (final value) => onChanged( context, value - ? TransactionOption.transferKeepAlive - : TransactionOption.transfer, + ? BalanceTransactionType.transferKeepAlive + : BalanceTransactionType.transfer, ), text: 'choose_transfer_keep_alive'.tr(), ), diff --git a/pubspec.lock b/pubspec.lock index 1db1d98c..b88e739c 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -1151,8 +1151,8 @@ packages: dependency: "direct main" description: path: "." - ref: "0d130d746954219bd165c96906f971ec1c5556a8" - resolved-ref: "0d130d746954219bd165c96906f971ec1c5556a8" + ref: a63cd4d4229c1a93401110c747268a46f8853310 + resolved-ref: a63cd4d4229c1a93401110c747268a46f8853310 url: "https://github.com/L3odr0id/polkawallet_sdk.git" source: git version: "0.5.1" diff --git a/pubspec.yaml b/pubspec.yaml index 2871edfc..4a49d371 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -63,7 +63,7 @@ dependencies: polkawallet_sdk: #0.5.1 git: url: https://github.com/L3odr0id/polkawallet_sdk.git - ref: 0d130d746954219bd165c96906f971ec1c5556a8 # release/0.5.1 # branch name + ref: a63cd4d4229c1a93401110c747268a46f8853310 # release/0.5.1 # branch name ## Code gen copy_with_extension: ^5.0.3 From 602c95364f662a04e01e4c1e851534be05ad089c Mon Sep 17 00:00:00 2001 From: L3odr0id Date: Tue, 31 Oct 2023 11:07:51 +0300 Subject: [PATCH 7/7] Version 2.9.0+31 --- lib/core/polkawallet/utils/transfer_type.dart | 18 ---- lib/core/polkawallet/utils/tx_info.dart | 82 ----------------- lib/core/polkawallet/utils/tx_params.dart | 84 ----------------- .../widgets/preview_save_button.dart | 2 +- .../bloc/transfer_info_bloc.dart | 3 +- .../domain/entities/transaction.dart | 2 - .../domain/entities/transfer.dart | 45 ++++----- .../domain/entities/transfer_history_ui.dart | 2 +- .../domain/entities/transfer_meta_dto.dart | 91 ------------------- .../bloc/assets_get_extrisincs_cubit.dart | 1 - .../widgets/from_address_textfield.dart | 1 - pubspec.lock | 4 +- pubspec.yaml | 4 +- 13 files changed, 31 insertions(+), 308 deletions(-) delete mode 100644 lib/core/polkawallet/utils/transfer_type.dart delete mode 100644 lib/core/polkawallet/utils/tx_info.dart delete mode 100644 lib/core/polkawallet/utils/tx_params.dart diff --git a/lib/core/polkawallet/utils/transfer_type.dart b/lib/core/polkawallet/utils/transfer_type.dart deleted file mode 100644 index 689d62dc..00000000 --- a/lib/core/polkawallet/utils/transfer_type.dart +++ /dev/null @@ -1,18 +0,0 @@ -// class TransferTypeValue { -// static const TransactionOption defaultType = -// TransactionOption.transferKeepAlive; - -// const TransferTypeValue(this.type); - -// final TransactionOption type; - -// @override -// String toString() { -// return type.name; -// } -// } - -// enum TransactionOption { -// transfer, -// transferKeepAlive, -// } diff --git a/lib/core/polkawallet/utils/tx_info.dart b/lib/core/polkawallet/utils/tx_info.dart deleted file mode 100644 index 62b38477..00000000 --- a/lib/core/polkawallet/utils/tx_info.dart +++ /dev/null @@ -1,82 +0,0 @@ -// import 'package:polkawallet_sdk/api/types/txInfoData.dart'; -// import 'package:polkawallet_sdk/plugin/store/balances.dart'; -// import 'package:polkawallet_sdk/storage/types/keyPairData.dart'; -// import 'package:threedpass/core/polkawallet/utils/transfer_type.dart'; -// import 'package:threedpass/core/polkawallet/utils/tx_params.dart'; - -// abstract class TransferTxInfoI { -// final KeyPairData senderData; -// final int decimals; -// final TransactionOption transferType; -// final String toAddress; -// final double amount; - -// const TransferTxInfoI({ -// required this.decimals, -// required this.senderData, -// required this.amount, -// required this.toAddress, -// required this.transferType, -// }); - -// TxInfoData txInfo(); -// TxParams params(); -// } - -// class AssetsTransferTx extends TransferTxInfoI { -// final TokenBalanceData tokenBalanceData; - -// const AssetsTransferTx({ -// required super.decimals, -// required super.senderData, -// required super.amount, -// required super.toAddress, -// required super.transferType, -// required this.tokenBalanceData, -// }); - -// @override -// TxInfoData txInfo() => TxInfoData( -// 'assets', -// TransferTypeValue(transferType).toString(), -// TxSenderData(senderData.address, senderData.pubKey), -// ); - -// @override -// TxParams params() { -// return AssetsTxParams( -// amount: amount, -// toAddress: toAddress, -// tokenBalanceData: tokenBalanceData, -// ); -// } -// } - -// class CoinsTransferTx extends TransferTxInfoI { -// const CoinsTransferTx({ -// required super.decimals, -// required super.senderData, -// required super.amount, -// required super.toAddress, -// required super.transferType, -// }); - -// @override -// TxInfoData txInfo() => TxInfoData( -// 'balances', -// TransferTypeValue(transferType).toString(), -// TxSenderData( -// senderData.address, -// senderData.pubKey, -// ), -// ); - -// @override -// TxParams params() { -// return CoinsTxParams( -// amount: amount, -// decimals: decimals, -// toAddress: toAddress, -// ); -// } -// } diff --git a/lib/core/polkawallet/utils/tx_params.dart b/lib/core/polkawallet/utils/tx_params.dart deleted file mode 100644 index 97016019..00000000 --- a/lib/core/polkawallet/utils/tx_params.dart +++ /dev/null @@ -1,84 +0,0 @@ -// import 'package:polkawallet_sdk/plugin/store/balances.dart'; -// import 'package:threedpass/core/polkawallet/utils/balance_utils.dart'; - -// abstract class TxParams { -// const TxParams(); - -// List paramsToSend(); -// String get toAddress; -// double get amount; - -// TxParamsType get type; -// } - -// class CoinsTxParams extends TxParams { -// const CoinsTxParams({ -// required this.amount, -// required this.decimals, -// required this.toAddress, -// }); - -// @override -// final double amount; -// final int decimals; -// @override -// final String toAddress; - -// @override -// List paramsToSend() { -// final realAmount = BalanceUtils.tokenInt( -// amount.toString(), -// decimals, -// ); - -// return [ -// // params.to -// toAddress, -// // params.amount -// realAmount.toString(), -// ]; -// } - -// @override -// TxParamsType get type => TxParamsType.coins; -// } - -// class AssetsTxParams extends TxParams { -// const AssetsTxParams({ -// required this.amount, -// required this.toAddress, -// required this.tokenBalanceData, -// }); - -// final TokenBalanceData tokenBalanceData; -// @override -// final double amount; -// @override -// final String toAddress; - -// @override -// List paramsToSend() { -// // https://polkadot.js.org/docs/substrate/extrinsics/#transferid-compactu32-target-multiaddress-amount-compactu128 -// final realAmount = BalanceUtils.tokenInt( -// amount.toString(), -// tokenBalanceData.decimals ?? 0, -// ); - -// if (tokenBalanceData.id == null) { -// throw Exception('TokenBalanceData.id is null'); -// } - -// return [ -// tokenBalanceData.id!, -// // params.to -// toAddress, -// // params.amount -// realAmount.toString(), -// ]; -// } - -// @override -// TxParamsType get type => TxParamsType.assets; -// } - -// enum TxParamsType { coins, assets } diff --git a/lib/features/preview_page/presentation/widgets/preview_save_button.dart b/lib/features/preview_page/presentation/widgets/preview_save_button.dart index 5b66197a..9de6fbe4 100644 --- a/lib/features/preview_page/presentation/widgets/preview_save_button.dart +++ b/lib/features/preview_page/presentation/widgets/preview_save_button.dart @@ -52,7 +52,7 @@ class PreviewSaveButton extends StatelessWidget { return D3pElevatedButton( minimumSize: const Size.fromHeight(46), text: title, - onPressed: () => routeToPush.show(context), + onPressed: () => routeToPush.push(context), ); } } diff --git a/lib/features/wallet_screen/bloc/transfer_info_bloc.dart b/lib/features/wallet_screen/bloc/transfer_info_bloc.dart index 53725694..c5be0c69 100644 --- a/lib/features/wallet_screen/bloc/transfer_info_bloc.dart +++ b/lib/features/wallet_screen/bloc/transfer_info_bloc.dart @@ -15,8 +15,6 @@ import 'package:threedpass/core/polkawallet/bloc/app_service_cubit.dart'; import 'package:threedpass/core/polkawallet/non_native_tokens_api.dart'; import 'package:threedpass/core/polkawallet/utils/balance_utils.dart'; import 'package:threedpass/core/polkawallet/utils/network_state_data_extension.dart'; -import 'package:threedpass/core/polkawallet/utils/transfer_type.dart'; -import 'package:threedpass/core/polkawallet/utils/tx_info.dart'; import 'package:threedpass/features/wallet_screen/bloc/notifications_cubit.dart'; import 'package:threedpass/features/wallet_screen/domain/entities/transfer.dart'; import 'package:threedpass/features/wallet_screen/domain/entities/transfer_meta_dto.dart'; @@ -261,6 +259,7 @@ class TransferInfoBloc BalanceUtils.balanceToDouble(rawAvaliableBalance, decimals); balanceCacheNotifier.value[address] = balance; } + // ignore: invalid_use_of_protected_member, invalid_use_of_visible_for_testing_member balanceCacheNotifier.notifyListeners(); } } diff --git a/lib/features/wallet_screen/domain/entities/transaction.dart b/lib/features/wallet_screen/domain/entities/transaction.dart index 8407597e..c3615273 100644 --- a/lib/features/wallet_screen/domain/entities/transaction.dart +++ b/lib/features/wallet_screen/domain/entities/transaction.dart @@ -1,9 +1,7 @@ import 'dart:async'; import 'package:auto_route/auto_route.dart'; -import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; -import 'package:fluttertoast/fluttertoast.dart'; import 'package:polkawallet_sdk/p3d/tx_info.dart'; import 'package:threedpass/core/polkawallet/app_service.dart'; import 'package:threedpass/core/widgets/default_loading_dialog.dart'; diff --git a/lib/features/wallet_screen/domain/entities/transfer.dart b/lib/features/wallet_screen/domain/entities/transfer.dart index 2a846ecf..5cfe4a96 100644 --- a/lib/features/wallet_screen/domain/entities/transfer.dart +++ b/lib/features/wallet_screen/domain/entities/transfer.dart @@ -4,7 +4,6 @@ import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:fluttertoast/fluttertoast.dart'; -import 'package:polkawallet_sdk/api/types/txInfoData.dart'; import 'package:polkawallet_sdk/p3d/tx_info.dart'; import 'package:polkawallet_sdk/p3d/tx_params.dart'; import 'package:threedpass/core/polkawallet/app_service.dart'; @@ -183,15 +182,17 @@ class Transfer { notificationsCubit.add(element); }); debugPrint('SingleTransaction'); - unawaited(SingleTransaction( - addHandler: addHandlerV, - appService: appService, - context: context, - finishNotificationWithError: finishNotificationWithErrorV, - globalContext: globalContext, - password: passwords.first, - txInfoMeta: metaInfos.first, - ).send()); + unawaited( + SingleTransaction( + addHandler: addHandlerV, + appService: appService, + context: context, + finishNotificationWithError: finishNotificationWithErrorV, + globalContext: globalContext, + password: passwords.first, + txInfoMeta: metaInfos.first, + ).send(), + ); }, onSecond: () async { notifications.forEach((final element) { @@ -214,17 +215,19 @@ class Transfer { notificationsCubit.add(element); }); debugPrint('MultiTxMultiSender'); - unawaited(MultiTxMultiSender( - addHandler: addHandlerV, - appService: appService, - context: context, - finishNotificationWithError: finishNotificationWithErrorV, - globalContext: globalContext, - // txInfos: txInfos, - // params: params.map((final e) => e.paramsToSend()).toList(), - txInfoMetas: metaInfos, - passwords: passwords, - ).send()); + unawaited( + MultiTxMultiSender( + addHandler: addHandlerV, + appService: appService, + context: context, + finishNotificationWithError: finishNotificationWithErrorV, + globalContext: globalContext, + // txInfos: txInfos, + // params: params.map((final e) => e.paramsToSend()).toList(), + txInfoMetas: metaInfos, + passwords: passwords, + ).send(), + ); }, onError: () async { debugPrint('Transfer case split Error'); diff --git a/lib/features/wallet_screen/domain/entities/transfer_history_ui.dart b/lib/features/wallet_screen/domain/entities/transfer_history_ui.dart index 2c5e7538..ef206f36 100644 --- a/lib/features/wallet_screen/domain/entities/transfer_history_ui.dart +++ b/lib/features/wallet_screen/domain/entities/transfer_history_ui.dart @@ -15,7 +15,7 @@ class TransferHistoryUI { final String fromAddress; final String toAddress; - /// Its says assets were send FROM this TO another + /// It says assets were send FROM this TO another final TransferDirection direction; final int decimals; diff --git a/lib/features/wallet_screen/domain/entities/transfer_meta_dto.dart b/lib/features/wallet_screen/domain/entities/transfer_meta_dto.dart index 51e9f55c..791b8287 100644 --- a/lib/features/wallet_screen/domain/entities/transfer_meta_dto.dart +++ b/lib/features/wallet_screen/domain/entities/transfer_meta_dto.dart @@ -35,95 +35,4 @@ class AssetTransferMetaDTO extends TransferMetaDTO { final MetaInfoType type = MetaInfoType.asset; } -// class CoinsTransferMetaDTO extends TransferMetaDTO { -// final String coinName; -// final CoinsTransferTx txInfoValue; -// final AppService appService; - -// CoinsTransferMetaDTO({ -// required this.coinName, -// required this.appService, -// }) : txInfoValue = CoinsTransferTx( -// appService: appService, -// ); - -// @override -// MetaInfoType get type => MetaInfoType.coin; - -// @override -// double getBalance() { -// appService.plugin.sdk.api.account.queryBalance(address) -// return BalanceUtils.balanceToDouble( -// appService.chosenAccountBalance.value.availableBalance as String, -// appService.networkStateData.safeDecimals, -// ); -// } - -// @override -// int get decimals => appService.networkStateData.safeDecimals; - -// @override -// String getName() { -// return coinName; -// } - -// @override -// TxInfoData getTxInfo(final TransferType transferType) { -// return txInfoValue.txInfo(transferType); -// } - -// @override -// List getParams( -// final String? amount, -// final String toAddress, -// ) { -// return txInfoValue.params(amount, toAddress); -// } -// } - -// class AssetTransferMetaDTO extends TransferMetaDTO { -// final TokenBalanceData tokenBalanceData; -// final AssetsTransferTx txInfoValue; - -// AssetTransferMetaDTO({ -// required this.tokenBalanceData, -// required final AppService appService, -// }) : txInfoValue = AssetsTransferTx( -// appService: appService, -// tokenBalanceData: tokenBalanceData, -// ); - -// @override -// MetaInfoType get type => MetaInfoType.asset; - -// @override -// double getBalance() { -// return BalanceUtils.balanceToDouble( -// tokenBalanceData.amount!, -// tokenBalanceData.decimals ?? 12, -// ); -// } - -// @override -// String getName() { -// return tokenBalanceData.symbol ?? ''; -// } - -// @override -// TxInfoData getTxInfo(final TransferType transferType) { -// return txInfoValue.txInfo(transferType); -// } - -// @override -// int get decimals => tokenBalanceData.decimals ?? 12; - -// @override -// List getParams( -// final String? amount, -// final String toAddress, -// ) { -// return txInfoValue.params(amount, toAddress); -// } -// } - enum MetaInfoType { asset, coin } diff --git a/lib/features/wallet_screen/presentation/non_native_token_screen/bloc/assets_get_extrisincs_cubit.dart b/lib/features/wallet_screen/presentation/non_native_token_screen/bloc/assets_get_extrisincs_cubit.dart index 329f0260..4d029477 100644 --- a/lib/features/wallet_screen/presentation/non_native_token_screen/bloc/assets_get_extrisincs_cubit.dart +++ b/lib/features/wallet_screen/presentation/non_native_token_screen/bloc/assets_get_extrisincs_cubit.dart @@ -14,7 +14,6 @@ import 'package:threedpass/features/wallet_screen/presentation/non_native_token_ import 'package:threedpass/features/wallet_screen/presentation/non_native_token_screen/domain/usecases/get_events_usecase.dart'; import 'package:threedpass/setup.dart'; -// TODO Maybe parse all extrinsics, not only account holder to get all incoming transactions class AssetsGetExtrinsicsCubit extends Cubit { AssetsGetExtrinsicsCubit({ required this.getExtrinsics, diff --git a/lib/features/wallet_screen/presentation/transfer_page/widgets/from_address_textfield.dart b/lib/features/wallet_screen/presentation/transfer_page/widgets/from_address_textfield.dart index 9f5ccfa9..f65b8663 100644 --- a/lib/features/wallet_screen/presentation/transfer_page/widgets/from_address_textfield.dart +++ b/lib/features/wallet_screen/presentation/transfer_page/widgets/from_address_textfield.dart @@ -37,7 +37,6 @@ class FromAddressTextField extends StatelessWidget { final textStyle = Theme.of(context).customTextStyles; final colors = Theme.of(context).customColors; - // TODO MAKE BUTTON TO COPY PASSWORD FROM TOP ACCOUNT return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ diff --git a/pubspec.lock b/pubspec.lock index b88e739c..796b1390 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -1151,8 +1151,8 @@ packages: dependency: "direct main" description: path: "." - ref: a63cd4d4229c1a93401110c747268a46f8853310 - resolved-ref: a63cd4d4229c1a93401110c747268a46f8853310 + ref: a8418594529fe60dca8d9a773ea044b8af3378ee + resolved-ref: a8418594529fe60dca8d9a773ea044b8af3378ee url: "https://github.com/L3odr0id/polkawallet_sdk.git" source: git version: "0.5.1" diff --git a/pubspec.yaml b/pubspec.yaml index 4a49d371..9b0bc7f5 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -10,7 +10,7 @@ publish_to: 'none' # In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion. # Read more about iOS versioning at # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html -version: 2.8.0+30 +version: 2.9.0+31 environment: sdk: ">=3.0.6 <3.0.7" @@ -63,7 +63,7 @@ dependencies: polkawallet_sdk: #0.5.1 git: url: https://github.com/L3odr0id/polkawallet_sdk.git - ref: a63cd4d4229c1a93401110c747268a46f8853310 # release/0.5.1 # branch name + ref: a8418594529fe60dca8d9a773ea044b8af3378ee # release/0.5.1 # branch name ## Code gen copy_with_extension: ^5.0.3