From 7455ab55f5da81d2e20c6df93483c45d24122aa3 Mon Sep 17 00:00:00 2001 From: julian Date: Wed, 1 May 2024 09:13:47 -0600 Subject: [PATCH] use new frost step text field widget --- .../new/steps/frost_create_step_1b.dart | 223 ++---------------- .../new/steps/frost_create_step_2.dart | 152 ++---------- .../new/steps/frost_create_step_3.dart | 146 ++---------- .../reshare/frost_reshare_step_1b.dart | 140 +---------- .../reshare/frost_reshare_step_1c.dart | 220 ++--------------- .../reshare/frost_reshare_step_3abd.dart | 156 ++---------- lib/widgets/textfields/frost_step_field.dart | 35 +-- 7 files changed, 124 insertions(+), 948 deletions(-) diff --git a/lib/pages/add_wallet_views/frost_ms/new/steps/frost_create_step_1b.dart b/lib/pages/add_wallet_views/frost_ms/new/steps/frost_create_step_1b.dart index ff9c01729..f95991f3e 100644 --- a/lib/pages/add_wallet_views/frost_ms/new/steps/frost_create_step_1b.dart +++ b/lib/pages/add_wallet_views/frost_ms/new/steps/frost_create_step_1b.dart @@ -1,24 +1,14 @@ -import 'dart:async'; - -import 'package:barcode_scan2/barcode_scan2.dart'; import 'package:flutter/material.dart'; -import 'package:flutter/services.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:stackwallet/pages/add_wallet_views/frost_ms/new/steps/frost_route_generator.dart'; import 'package:stackwallet/providers/frost_wallet/frost_wallet_providers.dart'; import 'package:stackwallet/services/frost.dart'; -import 'package:stackwallet/utilities/constants.dart'; -import 'package:stackwallet/utilities/logger.dart'; import 'package:stackwallet/utilities/text_styles.dart'; import 'package:stackwallet/utilities/util.dart'; import 'package:stackwallet/widgets/desktop/primary_button.dart'; import 'package:stackwallet/widgets/frost_step_user_steps.dart'; -import 'package:stackwallet/widgets/icon_widgets/clipboard_icon.dart'; -import 'package:stackwallet/widgets/icon_widgets/qrcode_icon.dart'; -import 'package:stackwallet/widgets/icon_widgets/x_icon.dart'; import 'package:stackwallet/widgets/stack_dialog.dart'; -import 'package:stackwallet/widgets/stack_text_field.dart'; -import 'package:stackwallet/widgets/textfield_icon_button.dart'; +import 'package:stackwallet/widgets/textfields/frost_step_field.dart'; class FrostCreateStep1b extends ConsumerStatefulWidget { const FrostCreateStep1b({super.key}); @@ -76,199 +66,32 @@ class _FrostCreateStep1bState extends ConsumerState { const SizedBox( height: 16, ), - ClipRRect( - borderRadius: BorderRadius.circular( - Constants.size.circularBorderRadius, - ), - child: TextField( - key: const Key("frMyNameTextFieldKey"), - controller: myNameFieldController, - onChanged: (_) { - setState(() { - _nameEmpty = myNameFieldController.text.isEmpty; - }); - }, - focusNode: myNameFocusNode, - readOnly: false, - autocorrect: false, - enableSuggestions: false, - style: STextStyles.field(context), - decoration: standardInputDecoration( - "My name", - myNameFocusNode, - context, - ).copyWith( - contentPadding: const EdgeInsets.only( - left: 16, - top: 6, - bottom: 8, - right: 5, - ), - suffixIcon: Padding( - padding: _nameEmpty - ? const EdgeInsets.only(right: 8) - : const EdgeInsets.only(right: 0), - child: UnconstrainedBox( - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceAround, - children: [ - !_nameEmpty - ? TextFieldIconButton( - semanticsLabel: - "Clear Button. Clears The Config Field.", - key: const Key("frMyNameClearButtonKey"), - onTap: () { - myNameFieldController.text = ""; - - setState(() { - _nameEmpty = true; - }); - }, - child: const XIcon(), - ) - : TextFieldIconButton( - semanticsLabel: - "Paste Button. Pastes From Clipboard To Name Field.", - key: const Key("frMyNamePasteButtonKey"), - onTap: () async { - final ClipboardData? data = - await Clipboard.getData( - Clipboard.kTextPlain); - if (data?.text != null && - data!.text!.isNotEmpty) { - myNameFieldController.text = - data.text!.trim(); - } - - setState(() { - _nameEmpty = - myNameFieldController.text.isEmpty; - }); - }, - child: _nameEmpty - ? const ClipboardIcon() - : const XIcon(), - ), - ], - ), - ), - ), - ), - ), + FrostStepField( + controller: myNameFieldController, + focusNode: myNameFocusNode, + showQrScanOption: false, + label: "My name", + hint: "Enter your name", + onChanged: (_) { + setState(() { + _nameEmpty = myNameFieldController.text.isEmpty; + }); + }, ), const SizedBox( height: 16, ), - ClipRRect( - borderRadius: BorderRadius.circular( - Constants.size.circularBorderRadius, - ), - child: TextField( - key: const Key("frConfigTextFieldKey"), - controller: configFieldController, - onChanged: (_) { - setState(() { - _configEmpty = configFieldController.text.isEmpty; - }); - }, - focusNode: configFocusNode, - readOnly: false, - autocorrect: false, - enableSuggestions: false, - style: STextStyles.field(context), - decoration: standardInputDecoration( - "Enter config", - configFocusNode, - context, - ).copyWith( - contentPadding: const EdgeInsets.only( - left: 16, - top: 6, - bottom: 8, - right: 5, - ), - suffixIcon: Padding( - padding: _configEmpty - ? const EdgeInsets.only(right: 8) - : const EdgeInsets.only(right: 0), - child: UnconstrainedBox( - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceAround, - children: [ - !_configEmpty - ? TextFieldIconButton( - semanticsLabel: - "Clear Button. Clears The Config Field.", - key: const Key("frConfigClearButtonKey"), - onTap: () { - configFieldController.text = ""; - - setState(() { - _configEmpty = true; - }); - }, - child: const XIcon(), - ) - : TextFieldIconButton( - semanticsLabel: - "Paste Button. Pastes From Clipboard To Config Field Input.", - key: const Key("frConfigPasteButtonKey"), - onTap: () async { - final ClipboardData? data = - await Clipboard.getData( - Clipboard.kTextPlain); - if (data?.text != null && - data!.text!.isNotEmpty) { - configFieldController.text = - data.text!.trim(); - } - - setState(() { - _configEmpty = - configFieldController.text.isEmpty; - }); - }, - child: _configEmpty - ? const ClipboardIcon() - : const XIcon(), - ), - if (_configEmpty) - TextFieldIconButton( - semanticsLabel: - "Scan QR Button. Opens Camera For Scanning QR Code.", - key: const Key("frConfigScanQrButtonKey"), - onTap: () async { - try { - if (FocusScope.of(context).hasFocus) { - FocusScope.of(context).unfocus(); - await Future.delayed( - const Duration(milliseconds: 75)); - } - - final qrResult = await BarcodeScanner.scan(); - - configFieldController.text = - qrResult.rawContent; - - setState(() { - _configEmpty = - configFieldController.text.isEmpty; - }); - } on PlatformException catch (e, s) { - Logging.instance.log( - "Failed to get camera permissions while trying to scan qr code: $e\n$s", - level: LogLevel.Warning, - ); - } - }, - child: const QrCodeIcon(), - ) - ], - ), - ), - ), - ), - ), + FrostStepField( + controller: configFieldController, + focusNode: configFocusNode, + showQrScanOption: true, + label: "Enter config", + hint: "Enter config", + onChanged: (_) { + setState(() { + _configEmpty = configFieldController.text.isEmpty; + }); + }, ), const SizedBox( height: 16, diff --git a/lib/pages/add_wallet_views/frost_ms/new/steps/frost_create_step_2.dart b/lib/pages/add_wallet_views/frost_ms/new/steps/frost_create_step_2.dart index dea6b9dcb..259059adb 100644 --- a/lib/pages/add_wallet_views/frost_ms/new/steps/frost_create_step_2.dart +++ b/lib/pages/add_wallet_views/frost_ms/new/steps/frost_create_step_2.dart @@ -1,6 +1,4 @@ -import 'package:barcode_scan2/barcode_scan2.dart'; import 'package:flutter/material.dart'; -import 'package:flutter/services.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_svg/flutter_svg.dart'; import 'package:stackwallet/pages/add_wallet_views/frost_ms/new/steps/frost_route_generator.dart'; @@ -9,7 +7,6 @@ import 'package:stackwallet/providers/frost_wallet/frost_wallet_providers.dart'; import 'package:stackwallet/services/frost.dart'; import 'package:stackwallet/themes/stack_colors.dart'; import 'package:stackwallet/utilities/assets.dart'; -import 'package:stackwallet/utilities/constants.dart'; import 'package:stackwallet/utilities/logger.dart'; import 'package:stackwallet/utilities/text_styles.dart'; import 'package:stackwallet/utilities/util.dart'; @@ -19,12 +16,8 @@ import 'package:stackwallet/widgets/desktop/secondary_button.dart'; import 'package:stackwallet/widgets/detail_item.dart'; import 'package:stackwallet/widgets/dialogs/frost/frost_step_qr_dialog.dart'; import 'package:stackwallet/widgets/frost_step_user_steps.dart'; -import 'package:stackwallet/widgets/icon_widgets/clipboard_icon.dart'; -import 'package:stackwallet/widgets/icon_widgets/qrcode_icon.dart'; -import 'package:stackwallet/widgets/icon_widgets/x_icon.dart'; import 'package:stackwallet/widgets/stack_dialog.dart'; -import 'package:stackwallet/widgets/stack_text_field.dart'; -import 'package:stackwallet/widgets/textfield_icon_button.dart'; +import 'package:stackwallet/widgets/textfields/frost_step_field.dart'; class FrostCreateStep2 extends ConsumerStatefulWidget { const FrostCreateStep2({ @@ -135,135 +128,20 @@ class _FrostCreateStep2State extends ConsumerState { ), const SizedBox(height: 12), for (int i = 0; i < participants.length; i++) - Column( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - const SizedBox( - height: 12, - ), - Text( - participants[i], - style: STextStyles.w500_14(context), - ), - const SizedBox( - height: 4, - ), - ClipRRect( - borderRadius: BorderRadius.circular( - Constants.size.circularBorderRadius, - ), - child: TextField( - key: Key("frostCommitmentsTextFieldKey_$i"), - controller: controllers[i], - focusNode: focusNodes[i], - readOnly: false, - autocorrect: false, - enableSuggestions: false, - style: STextStyles.field(context), - onChanged: (_) { - setState(() { - fieldIsEmptyFlags[i] = controllers[i].text.isEmpty; - }); - }, - decoration: standardInputDecoration( - "Enter ${participants[i]}'s commitment", - focusNodes[i], - context, - ).copyWith( - contentPadding: const EdgeInsets.only( - left: 16, - top: 6, - bottom: 8, - right: 5, - ), - suffixIcon: Padding( - padding: fieldIsEmptyFlags[i] - ? const EdgeInsets.only(right: 8) - : const EdgeInsets.only(right: 0), - child: UnconstrainedBox( - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceAround, - children: [ - !fieldIsEmptyFlags[i] - ? TextFieldIconButton( - semanticsLabel: - "Clear Button. Clears The Commitment Field Input.", - key: Key( - "frostCommitmentsClearButtonKey_$i"), - onTap: () { - controllers[i].text = ""; - - setState(() { - fieldIsEmptyFlags[i] = true; - }); - }, - child: const XIcon(), - ) - : TextFieldIconButton( - semanticsLabel: - "Paste Button. Pastes From Clipboard To Commitment Field Input.", - key: Key( - "frostCommitmentsPasteButtonKey_$i"), - onTap: () async { - final ClipboardData? data = - await Clipboard.getData( - Clipboard.kTextPlain); - if (data?.text != null && - data!.text!.isNotEmpty) { - controllers[i].text = - data.text!.trim(); - } - - setState(() { - fieldIsEmptyFlags[i] = - controllers[i].text.isEmpty; - }); - }, - child: fieldIsEmptyFlags[i] - ? const ClipboardIcon() - : const XIcon(), - ), - if (fieldIsEmptyFlags[i]) - TextFieldIconButton( - semanticsLabel: - "Scan QR Button. Opens Camera For Scanning QR Code.", - key: - Key("frostCommitmentsScanQrButtonKey_$i"), - onTap: () async { - try { - if (FocusScope.of(context).hasFocus) { - FocusScope.of(context).unfocus(); - await Future.delayed( - const Duration(milliseconds: 75)); - } - - final qrResult = - await BarcodeScanner.scan(); - - controllers[i].text = qrResult.rawContent; - - setState(() { - fieldIsEmptyFlags[i] = - controllers[i].text.isEmpty; - }); - } on PlatformException catch (e, s) { - Logging.instance.log( - "Failed to get camera permissions while trying to scan qr code: $e\n$s", - level: LogLevel.Warning, - ); - } - }, - child: const QrCodeIcon(), - ), - ], - ), - ), - ), - ), - ), - ), - ], + Padding( + padding: const EdgeInsets.only(top: 12), + child: FrostStepField( + controller: controllers[i], + focusNode: focusNodes[i], + showQrScanOption: true, + label: participants[i], + hint: "Enter ${participants[i]}'s commitment", + onChanged: (_) { + setState(() { + fieldIsEmptyFlags[i] = controllers[i].text.isEmpty; + }); + }, + ), ), if (!Util.isDesktop) const Spacer(), const SizedBox(height: 12), diff --git a/lib/pages/add_wallet_views/frost_ms/new/steps/frost_create_step_3.dart b/lib/pages/add_wallet_views/frost_ms/new/steps/frost_create_step_3.dart index 1d6de5c39..d48107055 100644 --- a/lib/pages/add_wallet_views/frost_ms/new/steps/frost_create_step_3.dart +++ b/lib/pages/add_wallet_views/frost_ms/new/steps/frost_create_step_3.dart @@ -1,6 +1,4 @@ -import 'package:barcode_scan2/barcode_scan2.dart'; import 'package:flutter/material.dart'; -import 'package:flutter/services.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_svg/flutter_svg.dart'; import 'package:stackwallet/pages/add_wallet_views/frost_ms/new/steps/frost_route_generator.dart'; @@ -9,9 +7,7 @@ import 'package:stackwallet/providers/frost_wallet/frost_wallet_providers.dart'; import 'package:stackwallet/services/frost.dart'; import 'package:stackwallet/themes/stack_colors.dart'; import 'package:stackwallet/utilities/assets.dart'; -import 'package:stackwallet/utilities/constants.dart'; import 'package:stackwallet/utilities/logger.dart'; -import 'package:stackwallet/utilities/text_styles.dart'; import 'package:stackwallet/utilities/util.dart'; import 'package:stackwallet/widgets/custom_buttons/simple_copy_button.dart'; import 'package:stackwallet/widgets/desktop/primary_button.dart'; @@ -19,12 +15,8 @@ import 'package:stackwallet/widgets/desktop/secondary_button.dart'; import 'package:stackwallet/widgets/detail_item.dart'; import 'package:stackwallet/widgets/dialogs/frost/frost_step_qr_dialog.dart'; import 'package:stackwallet/widgets/frost_step_user_steps.dart'; -import 'package:stackwallet/widgets/icon_widgets/clipboard_icon.dart'; -import 'package:stackwallet/widgets/icon_widgets/qrcode_icon.dart'; -import 'package:stackwallet/widgets/icon_widgets/x_icon.dart'; import 'package:stackwallet/widgets/stack_dialog.dart'; -import 'package:stackwallet/widgets/stack_text_field.dart'; -import 'package:stackwallet/widgets/textfield_icon_button.dart'; +import 'package:stackwallet/widgets/textfields/frost_step_field.dart'; class FrostCreateStep3 extends ConsumerStatefulWidget { const FrostCreateStep3({super.key}); @@ -132,132 +124,26 @@ class _FrostCreateStep3State extends ConsumerState { ), const SizedBox(height: 12), for (int i = 0; i < participants.length; i++) - Column( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - const SizedBox( - height: 12, - ), - Text( - participants[i], - style: STextStyles.w500_14(context), - ), - const SizedBox( - height: 4, - ), - ClipRRect( - borderRadius: BorderRadius.circular( - Constants.size.circularBorderRadius, - ), - child: TextField( - key: Key("frSharesTextFieldKey_$i"), - controller: controllers[i], - focusNode: focusNodes[i], - readOnly: false, - autocorrect: false, - enableSuggestions: false, - style: STextStyles.field(context), - decoration: standardInputDecoration( - "Enter ${participants[i]}'s share", - focusNodes[i], - context, - ).copyWith( - contentPadding: const EdgeInsets.only( - left: 16, - top: 6, - bottom: 8, - right: 5, - ), - suffixIcon: Padding( - padding: fieldIsEmptyFlags[i] - ? const EdgeInsets.only(right: 8) - : const EdgeInsets.only(right: 0), - child: UnconstrainedBox( - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceAround, - children: [ - !fieldIsEmptyFlags[i] - ? TextFieldIconButton( - semanticsLabel: - "Clear Button. Clears The Share Field Input.", - key: Key("frSharesClearButtonKey_$i"), - onTap: () { - controllers[i].text = ""; - - setState(() { - fieldIsEmptyFlags[i] = true; - }); - }, - child: const XIcon(), - ) - : TextFieldIconButton( - semanticsLabel: - "Paste Button. Pastes From Clipboard To Share Field Input.", - key: Key("frSharesPasteButtonKey_$i"), - onTap: () async { - final ClipboardData? data = - await Clipboard.getData( - Clipboard.kTextPlain); - if (data?.text != null && - data!.text!.isNotEmpty) { - controllers[i].text = - data.text!.trim(); - } - - setState(() { - fieldIsEmptyFlags[i] = - controllers[i].text.isEmpty; - }); - }, - child: fieldIsEmptyFlags[i] - ? const ClipboardIcon() - : const XIcon(), - ), - if (fieldIsEmptyFlags[i]) - TextFieldIconButton( - semanticsLabel: - "Scan QR Button. Opens Camera For Scanning QR Code.", - key: Key("frSharesScanQrButtonKey_$i"), - onTap: () async { - try { - if (FocusScope.of(context).hasFocus) { - FocusScope.of(context).unfocus(); - await Future.delayed( - const Duration(milliseconds: 75)); - } - - final qrResult = - await BarcodeScanner.scan(); - - controllers[i].text = qrResult.rawContent; - - setState(() { - fieldIsEmptyFlags[i] = - controllers[i].text.isEmpty; - }); - } on PlatformException catch (e, s) { - Logging.instance.log( - "Failed to get camera permissions while trying to scan qr code: $e\n$s", - level: LogLevel.Warning, - ); - } - }, - child: const QrCodeIcon(), - ) - ], - ), - ), - ), - ), - ), - ), - ], + Padding( + padding: const EdgeInsets.only(top: 12), + child: FrostStepField( + controller: controllers[i], + focusNode: focusNodes[i], + showQrScanOption: true, + label: participants[i], + hint: "Enter ${participants[i]}'s share", + onChanged: (_) { + setState(() { + fieldIsEmptyFlags[i] = controllers[i].text.isEmpty; + }); + }, + ), ), if (!Util.isDesktop) const Spacer(), const SizedBox(height: 12), PrimaryButton( label: "Generate", + enabled: !fieldIsEmptyFlags.reduce((v, e) => v |= e), onPressed: () async { // check for empty commitments if (controllers diff --git a/lib/pages/add_wallet_views/frost_ms/reshare/frost_reshare_step_1b.dart b/lib/pages/add_wallet_views/frost_ms/reshare/frost_reshare_step_1b.dart index b9c41ec7d..998bc12f5 100644 --- a/lib/pages/add_wallet_views/frost_ms/reshare/frost_reshare_step_1b.dart +++ b/lib/pages/add_wallet_views/frost_ms/reshare/frost_reshare_step_1b.dart @@ -1,6 +1,4 @@ -import 'package:barcode_scan2/barcode_scan2.dart'; import 'package:flutter/material.dart'; -import 'package:flutter/services.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:frostdart/frostdart.dart'; import 'package:stackwallet/pages/add_wallet_views/frost_ms/new/steps/frost_route_generator.dart'; @@ -8,8 +6,6 @@ import 'package:stackwallet/providers/db/main_db_provider.dart'; import 'package:stackwallet/providers/frost_wallet/frost_wallet_providers.dart'; import 'package:stackwallet/providers/global/secure_store_provider.dart'; import 'package:stackwallet/services/frost.dart'; -import 'package:stackwallet/themes/stack_colors.dart'; -import 'package:stackwallet/utilities/constants.dart'; import 'package:stackwallet/utilities/format.dart'; import 'package:stackwallet/utilities/logger.dart'; import 'package:stackwallet/utilities/text_styles.dart'; @@ -17,12 +13,8 @@ import 'package:stackwallet/utilities/util.dart'; import 'package:stackwallet/wallets/isar/models/frost_wallet_info.dart'; import 'package:stackwallet/widgets/desktop/primary_button.dart'; import 'package:stackwallet/widgets/frost_step_user_steps.dart'; -import 'package:stackwallet/widgets/icon_widgets/clipboard_icon.dart'; -import 'package:stackwallet/widgets/icon_widgets/qrcode_icon.dart'; -import 'package:stackwallet/widgets/icon_widgets/x_icon.dart'; import 'package:stackwallet/widgets/stack_dialog.dart'; -import 'package:stackwallet/widgets/stack_text_field.dart'; -import 'package:stackwallet/widgets/textfield_icon_button.dart'; +import 'package:stackwallet/widgets/textfields/frost_step_field.dart'; class FrostReshareStep1b extends ConsumerStatefulWidget { const FrostReshareStep1b({ @@ -166,125 +158,17 @@ class _FrostReshareStep1bState extends ConsumerState { userSteps: info, ), const SizedBox(height: 20), - Text( - "Enter config", - style: STextStyles.w500_14(context).copyWith( - color: Theme.of(context).extension()!.textSubtitle1, - ), - ), - const SizedBox( - height: 10, - ), - ClipRRect( - borderRadius: BorderRadius.circular( - Constants.size.circularBorderRadius, - ), - child: TextField( - key: const Key("frConfigTextFieldKey"), - controller: configFieldController, - onChanged: (_) { - setState(() { - _configEmpty = configFieldController.text.isEmpty; - }); - }, - focusNode: configFocusNode, - readOnly: false, - autocorrect: false, - enableSuggestions: false, - style: STextStyles.field(context), - decoration: standardInputDecoration( - "Enter config", - configFocusNode, - context, - ).copyWith( - contentPadding: const EdgeInsets.only( - left: 16, - top: 6, - bottom: 8, - right: 5, - ), - suffixIcon: Padding( - padding: _configEmpty - ? const EdgeInsets.only(right: 8) - : const EdgeInsets.only(right: 0), - child: UnconstrainedBox( - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceAround, - children: [ - !_configEmpty - ? TextFieldIconButton( - semanticsLabel: - "Clear Button. Clears The Config Field.", - key: const Key("frConfigClearButtonKey"), - onTap: () { - configFieldController.text = ""; - - setState(() { - _configEmpty = true; - }); - }, - child: const XIcon(), - ) - : TextFieldIconButton( - semanticsLabel: - "Paste Button. Pastes From Clipboard To Config Field Input.", - key: const Key("frConfigPasteButtonKey"), - onTap: () async { - final ClipboardData? data = - await Clipboard.getData( - Clipboard.kTextPlain); - if (data?.text != null && - data!.text!.isNotEmpty) { - configFieldController.text = - data.text!.trim(); - } - - setState(() { - _configEmpty = - configFieldController.text.isEmpty; - }); - }, - child: _configEmpty - ? const ClipboardIcon() - : const XIcon(), - ), - if (_configEmpty) - TextFieldIconButton( - semanticsLabel: - "Scan QR Button. Opens Camera For Scanning QR Code.", - key: const Key("frConfigScanQrButtonKey"), - onTap: () async { - try { - if (FocusScope.of(context).hasFocus) { - FocusScope.of(context).unfocus(); - await Future.delayed( - const Duration(milliseconds: 75)); - } - - final qrResult = await BarcodeScanner.scan(); - - configFieldController.text = - qrResult.rawContent; - - setState(() { - _configEmpty = - configFieldController.text.isEmpty; - }); - } on PlatformException catch (e, s) { - Logging.instance.log( - "Failed to get camera permissions while trying to scan qr code: $e\n$s", - level: LogLevel.Warning, - ); - } - }, - child: const QrCodeIcon(), - ) - ], - ), - ), - ), - ), - ), + FrostStepField( + controller: configFieldController, + focusNode: configFocusNode, + showQrScanOption: true, + label: "Enter config", + hint: "Enter config", + onChanged: (_) { + setState(() { + _configEmpty = configFieldController.text.isEmpty; + }); + }, ), const SizedBox( height: 16, diff --git a/lib/pages/add_wallet_views/frost_ms/reshare/frost_reshare_step_1c.dart b/lib/pages/add_wallet_views/frost_ms/reshare/frost_reshare_step_1c.dart index 3e0e17fdf..56d28c499 100644 --- a/lib/pages/add_wallet_views/frost_ms/reshare/frost_reshare_step_1c.dart +++ b/lib/pages/add_wallet_views/frost_ms/reshare/frost_reshare_step_1c.dart @@ -1,12 +1,9 @@ import 'dart:async'; -import 'package:barcode_scan2/barcode_scan2.dart'; import 'package:flutter/material.dart'; -import 'package:flutter/services.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:stackwallet/pages/add_wallet_views/frost_ms/new/steps/frost_route_generator.dart'; import 'package:stackwallet/providers/frost_wallet/frost_wallet_providers.dart'; -import 'package:stackwallet/utilities/constants.dart'; import 'package:stackwallet/utilities/logger.dart'; import 'package:stackwallet/utilities/show_loading.dart'; import 'package:stackwallet/utilities/text_styles.dart'; @@ -15,12 +12,8 @@ import 'package:stackwallet/wallets/isar/models/wallet_info.dart'; import 'package:stackwallet/wallets/models/incomplete_frost_wallet.dart'; import 'package:stackwallet/widgets/desktop/primary_button.dart'; import 'package:stackwallet/widgets/frost_step_user_steps.dart'; -import 'package:stackwallet/widgets/icon_widgets/clipboard_icon.dart'; -import 'package:stackwallet/widgets/icon_widgets/qrcode_icon.dart'; -import 'package:stackwallet/widgets/icon_widgets/x_icon.dart'; import 'package:stackwallet/widgets/stack_dialog.dart'; -import 'package:stackwallet/widgets/stack_text_field.dart'; -import 'package:stackwallet/widgets/textfield_icon_button.dart'; +import 'package:stackwallet/widgets/textfields/frost_step_field.dart'; class FrostReshareStep1c extends ConsumerStatefulWidget { const FrostReshareStep1c({super.key}); @@ -95,199 +88,32 @@ class _FrostReshareStep1cState extends ConsumerState { const SizedBox( height: 16, ), - ClipRRect( - borderRadius: BorderRadius.circular( - Constants.size.circularBorderRadius, - ), - child: TextField( - key: const Key("frMyNameTextFieldKey"), - controller: myNameFieldController, - onChanged: (_) { - setState(() { - _nameEmpty = myNameFieldController.text.isEmpty; - }); - }, - focusNode: myNameFocusNode, - readOnly: false, - autocorrect: false, - enableSuggestions: false, - style: STextStyles.field(context), - decoration: standardInputDecoration( - "My name", - myNameFocusNode, - context, - ).copyWith( - contentPadding: const EdgeInsets.only( - left: 16, - top: 6, - bottom: 8, - right: 5, - ), - suffixIcon: Padding( - padding: _nameEmpty - ? const EdgeInsets.only(right: 8) - : const EdgeInsets.only(right: 0), - child: UnconstrainedBox( - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceAround, - children: [ - !_nameEmpty - ? TextFieldIconButton( - semanticsLabel: - "Clear Button. Clears The Config Field.", - key: const Key("frMyNameClearButtonKey"), - onTap: () { - myNameFieldController.text = ""; - - setState(() { - _nameEmpty = true; - }); - }, - child: const XIcon(), - ) - : TextFieldIconButton( - semanticsLabel: - "Paste Button. Pastes From Clipboard To Name Field.", - key: const Key("frMyNamePasteButtonKey"), - onTap: () async { - final ClipboardData? data = - await Clipboard.getData( - Clipboard.kTextPlain); - if (data?.text != null && - data!.text!.isNotEmpty) { - myNameFieldController.text = - data.text!.trim(); - } - - setState(() { - _nameEmpty = - myNameFieldController.text.isEmpty; - }); - }, - child: _nameEmpty - ? const ClipboardIcon() - : const XIcon(), - ), - ], - ), - ), - ), - ), - ), + FrostStepField( + controller: myNameFieldController, + focusNode: myNameFocusNode, + showQrScanOption: false, + label: "My name", + hint: "Enter your name", + onChanged: (_) { + setState(() { + _nameEmpty = myNameFieldController.text.isEmpty; + }); + }, ), const SizedBox( height: 16, ), - ClipRRect( - borderRadius: BorderRadius.circular( - Constants.size.circularBorderRadius, - ), - child: TextField( - key: const Key("frConfigTextFieldKey"), - controller: configFieldController, - onChanged: (_) { - setState(() { - _configEmpty = configFieldController.text.isEmpty; - }); - }, - focusNode: configFocusNode, - readOnly: false, - autocorrect: false, - enableSuggestions: false, - style: STextStyles.field(context), - decoration: standardInputDecoration( - "Enter config", - configFocusNode, - context, - ).copyWith( - contentPadding: const EdgeInsets.only( - left: 16, - top: 6, - bottom: 8, - right: 5, - ), - suffixIcon: Padding( - padding: _configEmpty - ? const EdgeInsets.only(right: 8) - : const EdgeInsets.only(right: 0), - child: UnconstrainedBox( - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceAround, - children: [ - !_configEmpty - ? TextFieldIconButton( - semanticsLabel: - "Clear Button. Clears The Config Field.", - key: const Key("frConfigClearButtonKey"), - onTap: () { - configFieldController.text = ""; - - setState(() { - _configEmpty = true; - }); - }, - child: const XIcon(), - ) - : TextFieldIconButton( - semanticsLabel: - "Paste Button. Pastes From Clipboard To Config Field Input.", - key: const Key("frConfigPasteButtonKey"), - onTap: () async { - final ClipboardData? data = - await Clipboard.getData( - Clipboard.kTextPlain); - if (data?.text != null && - data!.text!.isNotEmpty) { - configFieldController.text = - data.text!.trim(); - } - - setState(() { - _configEmpty = - configFieldController.text.isEmpty; - }); - }, - child: _configEmpty - ? const ClipboardIcon() - : const XIcon(), - ), - if (_configEmpty) - TextFieldIconButton( - semanticsLabel: - "Scan QR Button. Opens Camera For Scanning QR Code.", - key: const Key("frConfigScanQrButtonKey"), - onTap: () async { - try { - if (FocusScope.of(context).hasFocus) { - FocusScope.of(context).unfocus(); - await Future.delayed( - const Duration(milliseconds: 75)); - } - - final qrResult = await BarcodeScanner.scan(); - - configFieldController.text = - qrResult.rawContent; - - setState(() { - _configEmpty = - configFieldController.text.isEmpty; - }); - } on PlatformException catch (e, s) { - Logging.instance.log( - "Failed to get camera permissions while trying to scan qr code: $e\n$s", - level: LogLevel.Warning, - ); - } - }, - child: const QrCodeIcon(), - ) - ], - ), - ), - ), - ), - ), + FrostStepField( + controller: configFieldController, + focusNode: configFocusNode, + showQrScanOption: true, + label: "Enter config", + hint: "Enter config", + onChanged: (_) { + setState(() { + _configEmpty = configFieldController.text.isEmpty; + }); + }, ), const SizedBox( height: 16, diff --git a/lib/pages/add_wallet_views/frost_ms/reshare/frost_reshare_step_3abd.dart b/lib/pages/add_wallet_views/frost_ms/reshare/frost_reshare_step_3abd.dart index cf3f9344b..ba365d08a 100644 --- a/lib/pages/add_wallet_views/frost_ms/reshare/frost_reshare_step_3abd.dart +++ b/lib/pages/add_wallet_views/frost_ms/reshare/frost_reshare_step_3abd.dart @@ -1,8 +1,6 @@ import 'dart:ffi'; -import 'package:barcode_scan2/barcode_scan2.dart'; import 'package:flutter/material.dart'; -import 'package:flutter/services.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:qr_flutter/qr_flutter.dart'; import 'package:stackwallet/pages/add_wallet_views/frost_ms/new/steps/frost_route_generator.dart'; @@ -10,19 +8,13 @@ import 'package:stackwallet/pages/wallet_view/transaction_views/transaction_deta import 'package:stackwallet/providers/frost_wallet/frost_wallet_providers.dart'; import 'package:stackwallet/services/frost.dart'; import 'package:stackwallet/themes/stack_colors.dart'; -import 'package:stackwallet/utilities/constants.dart'; import 'package:stackwallet/utilities/logger.dart'; -import 'package:stackwallet/utilities/text_styles.dart'; import 'package:stackwallet/utilities/util.dart'; import 'package:stackwallet/widgets/custom_buttons/simple_copy_button.dart'; import 'package:stackwallet/widgets/desktop/primary_button.dart'; import 'package:stackwallet/widgets/detail_item.dart'; -import 'package:stackwallet/widgets/icon_widgets/clipboard_icon.dart'; -import 'package:stackwallet/widgets/icon_widgets/qrcode_icon.dart'; -import 'package:stackwallet/widgets/icon_widgets/x_icon.dart'; import 'package:stackwallet/widgets/stack_dialog.dart'; -import 'package:stackwallet/widgets/stack_text_field.dart'; -import 'package:stackwallet/widgets/textfield_icon_button.dart'; +import 'package:stackwallet/widgets/textfields/frost_step_field.dart'; class FrostReshareStep3abd extends ConsumerStatefulWidget { const FrostReshareStep3abd({super.key}); @@ -182,136 +174,22 @@ class _FrostReshareStep3abdState extends ConsumerState { crossAxisAlignment: CrossAxisAlignment.start, children: [ for (int i = 0; i < newParticipants.length; i++) - Column( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Padding( - padding: const EdgeInsets.symmetric(vertical: 8), - child: ClipRRect( - borderRadius: BorderRadius.circular( - Constants.size.circularBorderRadius, - ), - child: TextField( - key: Key("frostEncryptionKeyTextFieldKey_$i"), - controller: controllers[i], - focusNode: focusNodes[i], - readOnly: false, - autocorrect: false, - enableSuggestions: false, - style: STextStyles.field(context), - onChanged: (_) { - setState(() { - fieldIsEmptyFlags[i] = - controllers[i].text.isEmpty; - }); - }, - decoration: standardInputDecoration( - "Enter " - "${newParticipants[i]}" - "'s encryption key", - focusNodes[i], - context, - ).copyWith( - contentPadding: const EdgeInsets.only( - left: 16, - top: 6, - bottom: 8, - right: 5, - ), - suffixIcon: Padding( - padding: fieldIsEmptyFlags[i] - ? const EdgeInsets.only(right: 8) - : const EdgeInsets.only(right: 0), - child: UnconstrainedBox( - child: Row( - mainAxisAlignment: - MainAxisAlignment.spaceAround, - children: [ - !fieldIsEmptyFlags[i] - ? TextFieldIconButton( - semanticsLabel: - "Clear Button. Clears The Encryption Key Field Input.", - key: Key( - "frostEncryptionKeyClearButtonKey_$i"), - onTap: () { - controllers[i].text = ""; - - setState(() { - fieldIsEmptyFlags[i] = true; - }); - }, - child: const XIcon(), - ) - : TextFieldIconButton( - semanticsLabel: - "Paste Button. Pastes From Clipboard To Encryption Key Field Input.", - key: Key( - "frostEncryptionKeyPasteButtonKey_$i"), - onTap: () async { - final ClipboardData? data = - await Clipboard.getData( - Clipboard.kTextPlain); - if (data?.text != null && - data!.text!.isNotEmpty) { - controllers[i].text = - data.text!.trim(); - } - - setState(() { - fieldIsEmptyFlags[i] = - controllers[i].text.isEmpty; - }); - }, - child: fieldIsEmptyFlags[i] - ? const ClipboardIcon() - : const XIcon(), - ), - if (fieldIsEmptyFlags[i]) - TextFieldIconButton( - semanticsLabel: "Scan QR Button. " - "Opens Camera For Scanning QR Code.", - key: Key( - "frostCommitmentsScanQrButtonKey_$i"), - onTap: () async { - try { - if (FocusScope.of(context) - .hasFocus) { - FocusScope.of(context).unfocus(); - await Future.delayed( - const Duration( - milliseconds: 75)); - } - - final qrResult = - await BarcodeScanner.scan(); - - controllers[i].text = - qrResult.rawContent; - - setState(() { - fieldIsEmptyFlags[i] = - controllers[i].text.isEmpty; - }); - } on PlatformException catch (e, s) { - Logging.instance.log( - "Failed to get camera permissions " - "while trying to scan qr code: $e\n$s", - level: LogLevel.Warning, - ); - } - }, - child: const QrCodeIcon(), - ), - ], - ), - ), - ), - ), - ), - ), - ), - ], + Padding( + padding: const EdgeInsets.only(top: 12), + child: FrostStepField( + controller: controllers[i], + focusNode: focusNodes[i], + showQrScanOption: true, + label: newParticipants[i], + hint: "Enter " + "${newParticipants[i]}" + "'s encryption key", + onChanged: (_) { + setState(() { + fieldIsEmptyFlags[i] = controllers[i].text.isEmpty; + }); + }, + ), ), ], ), diff --git a/lib/widgets/textfields/frost_step_field.dart b/lib/widgets/textfields/frost_step_field.dart index 63b16de97..7fd19ba3b 100644 --- a/lib/widgets/textfields/frost_step_field.dart +++ b/lib/widgets/textfields/frost_step_field.dart @@ -19,7 +19,7 @@ class FrostStepField extends StatefulWidget { required this.focusNode, this.label, this.hint, - // this.onChanged, + required this.onChanged, required this.showQrScanOption, }); @@ -27,7 +27,7 @@ class FrostStepField extends StatefulWidget { final FocusNode focusNode; final String? label; final String? hint; - // final void Function(String)? onChanged; + final void Function(String) onChanged; final bool showQrScanOption; @override @@ -51,10 +51,22 @@ class _FrostStepFieldState extends State { ), ); + late final void Function(String) _changed; + @override void initState() { _qrKey = widget.showQrScanOption ? UniqueKey() : null; _isEmpty = widget.controller.text.isEmpty; + + _changed = (value) { + if (context.mounted) { + widget.onChanged.call(value); + setState(() { + _isEmpty = widget.controller.text.isEmpty; + }); + } + }; + super.initState(); } @@ -82,12 +94,7 @@ class _FrostStepFieldState extends State { autocorrect: false, enableSuggestions: false, style: STextStyles.field(context), - // onChanged: widget.onChanged, - onChanged: (_) { - setState(() { - _isEmpty = widget.controller.text.isEmpty; - }); - }, + onChanged: _changed, decoration: InputDecoration( hintText: widget.hint, fillColor: widget.focusNode.hasFocus @@ -117,9 +124,7 @@ class _FrostStepFieldState extends State { onTap: () { widget.controller.text = ""; - setState(() { - _isEmpty = true; - }); + _changed(widget.controller.text); }, child: const XIcon(), ) @@ -134,9 +139,7 @@ class _FrostStepFieldState extends State { widget.controller.text = data.text!.trim(); } - setState(() { - _isEmpty = widget.controller.text.isEmpty; - }); + _changed(widget.controller.text); }, child: _isEmpty ? const ClipboardIcon() : const XIcon(), @@ -158,9 +161,7 @@ class _FrostStepFieldState extends State { widget.controller.text = qrResult.rawContent; - setState(() { - _isEmpty = widget.controller.text.isEmpty; - }); + _changed(widget.controller.text); } on PlatformException catch (e, s) { Logging.instance.log( "Failed to get camera permissions while trying to scan qr code: $e\n$s",