Skip to content

Commit

Permalink
refactor: text_filed widgets page independent (#648)
Browse files Browse the repository at this point in the history
* refactor: change widgets folders from voices_[name] to just [name] to be consistent

* refactor: Introduce VoicesTextField which is page independent and LoginXTextField which are tied to LoginBloc

* fix: voices_x_text_field child widget reference
  • Loading branch information
damian-molinski authored Jul 31, 2024
1 parent a729823 commit 64e5a80
Show file tree
Hide file tree
Showing 22 changed files with 202 additions and 96 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import 'package:catalyst_voices/pages/login/login.dart';
import 'package:catalyst_voices/widgets/widgets.dart';
import 'package:catalyst_voices/pages/login/login_email_text_filed.dart';
import 'package:catalyst_voices/pages/login/login_password_text_field.dart';
import 'package:flutter_test/flutter_test.dart';

final class LoginRobot {
Expand All @@ -16,14 +17,16 @@ final class LoginRobot {
}

Future<void> enterEmail(String email) async {
final emailTextField = find.byKey(EmailInput.emailInputKey);
final emailTextField = find.byKey(LoginEmailTextFiled.emailInputKey);
expect(emailTextField, findsOneWidget);
await widgetTester.enterText(emailTextField, email);
await widgetTester.pump();
}

Future<void> enterPassword(String password) async {
final passwordTextField = find.byKey(PasswordInput.passwordInputKey);
final passwordTextField = find.byKey(
LoginPasswordTextField.passwordInputKey,
);
expect(passwordTextField, findsOneWidget);
await widgetTester.enterText(passwordTextField, password);
await widgetTester.pump();
Expand Down
29 changes: 29 additions & 0 deletions catalyst_voices/lib/pages/login/login_email_text_filed.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import 'package:catalyst_voices/widgets/widgets.dart';
import 'package:catalyst_voices_blocs/catalyst_voices_blocs.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';

final class LoginEmailTextFiled extends StatelessWidget {
static const emailInputKey = Key('EmailInput');

const LoginEmailTextFiled({
super.key,
});

@override
Widget build(BuildContext context) {
return BlocBuilder<LoginBloc, LoginState>(
buildWhen: (previous, current) => previous.email != current.email,
builder: (context, state) {
return VoicesEmailTextField(
key: emailInputKey,
onChanged: (email) => _onEmailChanged(context, email),
);
},
);
}

void _onEmailChanged(BuildContext context, String email) {
context.read<LoginBloc>().add(LoginEmailChanged(email));
}
}
7 changes: 4 additions & 3 deletions catalyst_voices/lib/pages/login/login_form.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import 'package:catalyst_voices/pages/login/login.dart';
import 'package:catalyst_voices/widgets/widgets.dart';
import 'package:catalyst_voices/pages/login/login_email_text_filed.dart';
import 'package:catalyst_voices/pages/login/login_password_text_field.dart';
import 'package:catalyst_voices_blocs/catalyst_voices_blocs.dart';
import 'package:catalyst_voices_localization/catalyst_voices_localization.dart';
import 'package:flutter/material.dart';
Expand Down Expand Up @@ -51,9 +52,9 @@ final class LoginForm extends StatelessWidget {
),
),
const SizedBox(height: 30),
const EmailInput(),
const LoginEmailTextFiled(),
const SizedBox(height: 20),
const PasswordInput(),
const LoginPasswordTextField(),
const SizedBox(height: 20),
const SizedBox(
width: double.infinity,
Expand Down
29 changes: 29 additions & 0 deletions catalyst_voices/lib/pages/login/login_password_text_field.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import 'package:catalyst_voices/widgets/widgets.dart';
import 'package:catalyst_voices_blocs/catalyst_voices_blocs.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';

final class LoginPasswordTextField extends StatelessWidget {
static const passwordInputKey = Key('PasswordInput');

const LoginPasswordTextField({
super.key,
});

@override
Widget build(BuildContext context) {
return BlocBuilder<LoginBloc, LoginState>(
buildWhen: (previous, current) => previous.password != current.password,
builder: (context, state) {
return VoicesPasswordTextField(
key: passwordInputKey,
onChanged: (password) => _onPasswordChanged(context, password),
);
},
);
}

void _onPasswordChanged(BuildContext context, String password) {
context.read<LoginBloc>().add(LoginPasswordChanged(password));
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import 'package:catalyst_voices/widgets/voices_app_bar/actions/voices_app_bar_actions.dart';
import 'package:catalyst_voices/widgets/app_bar/actions/voices_app_bar_actions.dart';
import 'package:catalyst_voices_assets/catalyst_voices_assets.dart';
import 'package:catalyst_voices_brands/catalyst_voices_brands.dart';
import 'package:catalyst_voices_shared/catalyst_voices_shared.dart';
Expand Down
38 changes: 0 additions & 38 deletions catalyst_voices/lib/widgets/email_input.dart

This file was deleted.

46 changes: 0 additions & 46 deletions catalyst_voices/lib/widgets/password_input.dart

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import 'package:catalyst_voices/widgets/text_field/voices_text_field.dart';
import 'package:catalyst_voices_localization/catalyst_voices_localization.dart';
import 'package:flutter/material.dart';

final class VoicesEmailTextField extends StatelessWidget {
/// Emits new value when widget input changes
final ValueChanged<String>? onChanged;

const VoicesEmailTextField({
super.key,
this.onChanged,
});

@override
Widget build(BuildContext context) {
final l10n = context.l10n;
return VoicesTextField(
keyboardType: TextInputType.emailAddress,
textInputAction: TextInputAction.next,
onChanged: onChanged,
decoration: InputDecoration(
filled: true,
labelText: l10n.emailLabelText,
hintText: l10n.emailHintText,
errorText: l10n.emailErrorText,
border: const OutlineInputBorder(),
),
style: const TextStyle(
fontWeight: FontWeight.w500,
),
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import 'package:catalyst_voices/widgets/text_field/voices_text_field.dart';
import 'package:catalyst_voices_localization/catalyst_voices_localization.dart';
import 'package:flutter/material.dart';

final class VoicesPasswordTextField extends StatelessWidget {
/// Emits new value when widget input changes
final ValueChanged<String>? onChanged;

const VoicesPasswordTextField({
super.key,
this.onChanged,
});

@override
Widget build(BuildContext context) {
final l10n = context.l10n;
return VoicesTextField(
keyboardType: TextInputType.multiline,
obscureText: true,
textInputAction: TextInputAction.done,
onChanged: onChanged,
decoration: InputDecoration(
filled: true,
errorMaxLines: 2,
labelText: l10n.passwordLabelText,
hintText: l10n.passwordHintText,
errorText: l10n.passwordErrorText,
border: const OutlineInputBorder(),
),
style: const TextStyle(
fontWeight: FontWeight.w500,
),
);
}
}
59 changes: 59 additions & 0 deletions catalyst_voices/lib/widgets/text_field/voices_text_field.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import 'package:flutter/material.dart';

/// Base Voices TextField widget
class VoicesTextField extends StatelessWidget {
/// [TextField.controller]
final TextEditingController? controller;

/// [TextField.focusNode]
final FocusNode? focusNode;

/// [TextField.decoration]
final InputDecoration? decoration;

/// [TextField.keyboardType]
final TextInputType? keyboardType;

/// [TextField.textInputAction]
final TextInputAction? textInputAction;

/// [TextField.textCapitalization]
final TextCapitalization textCapitalization;

/// [TextField.style]
final TextStyle? style;

/// [TextField.obscureText]
final bool obscureText;

/// [TextField.onChanged]
final ValueChanged<String>? onChanged;

const VoicesTextField({
super.key,
this.controller,
this.focusNode,
this.decoration = const InputDecoration(),
this.keyboardType,
this.textInputAction,
this.textCapitalization = TextCapitalization.none,
this.style,
this.obscureText = false,
this.onChanged,
});

@override
Widget build(BuildContext context) {
return TextField(
controller: controller,
focusNode: focusNode,
decoration: decoration,
keyboardType: keyboardType,
textInputAction: textInputAction,
textCapitalization: textCapitalization,
style: style,
obscureText: obscureText,
onChanged: onChanged,
);
}
}
5 changes: 3 additions & 2 deletions catalyst_voices/lib/widgets/widgets.dart
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
export 'email_input.dart';
export 'password_input.dart';
export 'text_field/voices_email_text_field.dart';
export 'text_field/voices_password_text_field.dart';
export 'text_field/voices_text_field.dart';
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import 'package:catalyst_voices/widgets/app_bar/actions/voices_app_bar_actions.dart';
import 'package:catalyst_voices/widgets/app_bar/voices_app_bar.dart';
import 'package:catalyst_voices/widgets/drawer/voices_drawer.dart';
import 'package:catalyst_voices/widgets/menu/voices_expandable_list_tile.dart';
import 'package:catalyst_voices/widgets/menu/voices_list_tile.dart';
import 'package:catalyst_voices/widgets/voices_app_bar/actions/voices_app_bar_actions.dart';
import 'package:catalyst_voices/widgets/voices_app_bar/voices_app_bar.dart';
import 'package:catalyst_voices/widgets/voices_drawer/voices_drawer.dart';
import 'package:catalyst_voices_assets/catalyst_voices_assets.dart';
import 'package:flutter/material.dart';

Expand Down

0 comments on commit 64e5a80

Please sign in to comment.