diff --git a/catalyst_voices/apps/voices/lib/pages/account/delete_keychain_dialog.dart b/catalyst_voices/apps/voices/lib/pages/account/delete_keychain_dialog.dart index bfb3a7e89b0..ea199389f58 100644 --- a/catalyst_voices/apps/voices/lib/pages/account/delete_keychain_dialog.dart +++ b/catalyst_voices/apps/voices/lib/pages/account/delete_keychain_dialog.dart @@ -105,6 +105,7 @@ class _DeleteKeychainDialogState extends State { width: 300, child: VoicesTextField( controller: _textEditingController, + onFieldSubmitted: _removeKeychain, decoration: VoicesTextFieldDecoration( errorText: _errorText, errorMaxLines: 2, @@ -122,7 +123,7 @@ class _DeleteKeychainDialogState extends State { children: [ VoicesFilledButton( backgroundColor: Theme.of(context).colors.iconsError, - onTap: () async => _onRemoveKeychainTap(), + onTap: _removeKeychain, child: Text(context.l10n.delete), ), const SizedBox(width: 8), @@ -140,9 +141,8 @@ class _DeleteKeychainDialogState extends State { ); } - Future _onRemoveKeychainTap() async { - if (_textEditingController.text == - context.l10n.deleteKeychainDialogRemovingPhrase) { + void _removeKeychain([String? value]) { + if (_isDeleteConfirmed(value ?? _textEditingController.text)) { Navigator.pop(context, true); } else { setState(() { @@ -150,4 +150,8 @@ class _DeleteKeychainDialogState extends State { }); } } + + bool _isDeleteConfirmed(String value) { + return value == context.l10n.deleteKeychainDialogRemovingPhrase; + } } diff --git a/catalyst_voices/apps/voices/lib/pages/login/login_email_text_filed.dart b/catalyst_voices/apps/voices/lib/pages/login/login_email_text_filed.dart index 770d8ac3ada..7d8e4d6d96f 100644 --- a/catalyst_voices/apps/voices/lib/pages/login/login_email_text_filed.dart +++ b/catalyst_voices/apps/voices/lib/pages/login/login_email_text_filed.dart @@ -18,6 +18,7 @@ final class LoginEmailTextFiled extends StatelessWidget { return VoicesEmailTextField( key: emailInputKey, onChanged: (email) => _onEmailChanged(context, email), + onFieldSubmitted: (email) => _onEmailChanged(context, email), ); }, ); diff --git a/catalyst_voices/apps/voices/lib/pages/voting/voting_page.dart b/catalyst_voices/apps/voices/lib/pages/voting/voting_page.dart index 15bd6c4bdf8..d7042441953 100644 --- a/catalyst_voices/apps/voices/lib/pages/voting/voting_page.dart +++ b/catalyst_voices/apps/voices/lib/pages/voting/voting_page.dart @@ -121,6 +121,7 @@ class _UnlockedHeaderActions extends StatelessWidget { suffixIcon: VoicesAssets.icons.arrowTriangleDown.buildIcon(size: 16), ), + onFieldSubmitted: (value) {}, ), ), const SizedBox(width: 16), @@ -132,6 +133,7 @@ class _UnlockedHeaderActions extends StatelessWidget { hintText: 'Search proposals', prefixIcon: VoicesAssets.icons.search.buildIcon(), ), + onFieldSubmitted: (value) {}, ), ), IconButton( diff --git a/catalyst_voices/apps/voices/lib/widgets/text_field/voices_email_text_field.dart b/catalyst_voices/apps/voices/lib/widgets/text_field/voices_email_text_field.dart index e39beb61a47..418c7fa70e5 100644 --- a/catalyst_voices/apps/voices/lib/widgets/text_field/voices_email_text_field.dart +++ b/catalyst_voices/apps/voices/lib/widgets/text_field/voices_email_text_field.dart @@ -5,10 +5,12 @@ import 'package:flutter/material.dart'; final class VoicesEmailTextField extends StatelessWidget { /// Emits new value when widget input changes final ValueChanged? onChanged; + final ValueChanged onFieldSubmitted; const VoicesEmailTextField({ super.key, this.onChanged, + required this.onFieldSubmitted, }); @override @@ -18,6 +20,7 @@ final class VoicesEmailTextField extends StatelessWidget { keyboardType: TextInputType.emailAddress, textInputAction: TextInputAction.next, onChanged: onChanged, + onFieldSubmitted: onFieldSubmitted, decoration: VoicesTextFieldDecoration( labelText: l10n.emailLabelText, hintText: l10n.emailHintText, diff --git a/catalyst_voices/apps/voices/lib/widgets/text_field/voices_text_field.dart b/catalyst_voices/apps/voices/lib/widgets/text_field/voices_text_field.dart index 0c244f87f3a..31220324918 100644 --- a/catalyst_voices/apps/voices/lib/widgets/text_field/voices_text_field.dart +++ b/catalyst_voices/apps/voices/lib/widgets/text_field/voices_text_field.dart @@ -85,7 +85,10 @@ class VoicesTextField extends StatefulWidget { this.validator, this.onChanged, this.resizable, - this.onFieldSubmitted, + // Making it required but nullable because default behaviour is + // to make some action when user taps enter. Focus next field or anything + // else. + required this.onFieldSubmitted, this.onSaved, this.inputFormatters, }); diff --git a/catalyst_voices/apps/voices/test/widgets/text_field/voices_text_field_test.dart b/catalyst_voices/apps/voices/test/widgets/text_field/voices_text_field_test.dart index 965cf736a2a..7afb9e3c309 100644 --- a/catalyst_voices/apps/voices/test/widgets/text_field/voices_text_field_test.dart +++ b/catalyst_voices/apps/voices/test/widgets/text_field/voices_text_field_test.dart @@ -8,8 +8,10 @@ void main() { group('VoicesTextField Widget Tests', () { testWidgets('renders correctly with default parameters', (tester) async { await tester.pumpWidget( - const _MaterialApp( - child: VoicesTextField(), + _MaterialApp( + child: VoicesTextField( + onFieldSubmitted: (value) {}, + ), ), ); @@ -21,9 +23,10 @@ void main() { const labelText = 'Test Label'; await tester.pumpWidget( - const _MaterialApp( + _MaterialApp( child: VoicesTextField( - decoration: VoicesTextFieldDecoration(labelText: labelText), + decoration: const VoicesTextFieldDecoration(labelText: labelText), + onFieldSubmitted: (value) {}, ), ), ); @@ -39,6 +42,7 @@ void main() { _MaterialApp( child: VoicesTextField( controller: controller, + onFieldSubmitted: (value) {}, ), ), ); @@ -55,12 +59,13 @@ void main() { const errorText = 'Error message'; await tester.pumpWidget( - const _MaterialApp( + _MaterialApp( child: VoicesTextField( - decoration: VoicesTextFieldDecoration( + decoration: const VoicesTextFieldDecoration( hintText: hintText, errorText: errorText, ), + onFieldSubmitted: (value) {}, ), ), ); @@ -80,6 +85,7 @@ void main() { status: VoicesTextFieldStatus.error, errorMessage: errorText, ), + onFieldSubmitted: (value) {}, ), ), ); @@ -101,6 +107,7 @@ void main() { _MaterialApp( child: VoicesTextField( validator: VoicesTextFieldValidationResult.success(), + onFieldSubmitted: (value) {}, ), ), ); @@ -118,11 +125,13 @@ void main() { testWidgets('renders correctly when disabled', (tester) async { await tester.pumpWidget( - const _MaterialApp( + _MaterialApp( child: VoicesTextField( enabled: false, - decoration: - VoicesTextFieldDecoration(labelText: 'Disabled TextField'), + decoration: const VoicesTextFieldDecoration( + labelText: 'Disabled TextField', + ), + onFieldSubmitted: (value) {}, ), ), ); @@ -155,6 +164,7 @@ void main() { _MaterialApp( child: VoicesTextField( validator: validator, + onFieldSubmitted: (value) {}, ), ), ); @@ -186,6 +196,7 @@ void main() { _MaterialApp( child: VoicesTextField( validator: validator, + onFieldSubmitted: (value) {}, ), ), ); @@ -222,6 +233,7 @@ void main() { _MaterialApp( child: VoicesTextField( validator: validator, + onFieldSubmitted: (value) {}, ), ), ); diff --git a/catalyst_voices/utilities/uikit_example/lib/examples/voices_text_field_example.dart b/catalyst_voices/utilities/uikit_example/lib/examples/voices_text_field_example.dart index 286c22300df..059f16ab035 100644 --- a/catalyst_voices/utilities/uikit_example/lib/examples/voices_text_field_example.dart +++ b/catalyst_voices/utilities/uikit_example/lib/examples/voices_text_field_example.dart @@ -42,6 +42,7 @@ class _VoicesTextFieldExampleState extends State { suffixIcon: VoicesAssets.icons.chevronDown.buildIcon(), ), maxLength: 200, + onFieldSubmitted: (value) {}, ), ), SizedBox( @@ -56,6 +57,7 @@ class _VoicesTextFieldExampleState extends State { ), maxLength: 200, enabled: false, + onFieldSubmitted: (value) {}, ), ), SizedBox( @@ -70,6 +72,7 @@ class _VoicesTextFieldExampleState extends State { suffixIcon: Icon(Icons.error_outline), ), maxLength: 200, + onFieldSubmitted: (value) {}, ), ), SizedBox( @@ -83,6 +86,7 @@ class _VoicesTextFieldExampleState extends State { ), maxLength: 200, validator: VoicesTextFieldValidationResult.success(), + onFieldSubmitted: (value) {}, ), ), SizedBox( @@ -97,6 +101,7 @@ class _VoicesTextFieldExampleState extends State { maxLength: 200, validator: VoicesTextFieldValidationResult.warning('Warning message'), + onFieldSubmitted: (value) {}, ), ), SizedBox( @@ -111,6 +116,7 @@ class _VoicesTextFieldExampleState extends State { maxLength: 200, validator: VoicesTextFieldValidationResult.error('Error message'), + onFieldSubmitted: (value) {}, ), ), SizedBox( @@ -125,6 +131,7 @@ class _VoicesTextFieldExampleState extends State { maxLength: 200, validator: VoicesTextFieldValidationResult.success(), enabled: false, + onFieldSubmitted: (value) {}, ), ), SizedBox( @@ -140,6 +147,7 @@ class _VoicesTextFieldExampleState extends State { validator: VoicesTextFieldValidationResult.warning('Warning message'), enabled: false, + onFieldSubmitted: (value) {}, ), ), SizedBox( @@ -155,6 +163,7 @@ class _VoicesTextFieldExampleState extends State { validator: VoicesTextFieldValidationResult.error('Error message'), enabled: false, + onFieldSubmitted: (value) {}, ), ), SizedBox( @@ -188,6 +197,7 @@ class _VoicesTextFieldExampleState extends State { } }, maxLength: 200, + onFieldSubmitted: (value) {}, ), ), SizedBox( @@ -202,6 +212,7 @@ class _VoicesTextFieldExampleState extends State { maxLength: 200, minLines: 6, maxLines: 10, + onFieldSubmitted: (value) {}, ), ), SizedBox( @@ -212,6 +223,7 @@ class _VoicesTextFieldExampleState extends State { labelText: 'Resizable', ), maxLines: null, + onFieldSubmitted: (value) {}, ), ), ],