From b1d379b321d2f7c13a103b5a6a19638c2bb87078 Mon Sep 17 00:00:00 2001 From: mike doornenbal Date: Tue, 6 Feb 2024 16:05:46 +0100 Subject: [PATCH] fix: added Ci and linter --- .github/workflows/component-ci.yml | 14 +++++ .github/workflows/flutter.yml | 27 --------- CHANGELOG.md | 3 + analysis_options.yaml | 11 +++- lib/flutter_login.dart | 7 ++- lib/src/config/login_options.dart | 72 +++++++++++------------ lib/src/config/spacer_options.dart | 3 +- lib/src/service/login_validation.dart | 4 +- lib/src/widgets/email_password_login.dart | 32 +++++----- lib/src/widgets/forgot_password_form.dart | 38 ++++++------ lib/src/widgets/mfa_widget.dart | 60 +++++++++---------- pubspec.yaml | 7 ++- 12 files changed, 136 insertions(+), 142 deletions(-) create mode 100644 .github/workflows/component-ci.yml delete mode 100644 .github/workflows/flutter.yml diff --git a/.github/workflows/component-ci.yml b/.github/workflows/component-ci.yml new file mode 100644 index 0000000..ca69d49 --- /dev/null +++ b/.github/workflows/component-ci.yml @@ -0,0 +1,14 @@ +name: Iconica Standard Component CI Workflow +# Workflow Caller version: 2.0.0 + +on: + pull_request: + workflow_dispatch: + +jobs: + call-global-iconica-workflow: + uses: Iconica-Development/.github/.github/workflows/component-ci.yml@master + secrets: inherit + permissions: write-all + with: + subfolder: "." # add optional subfolder to run workflow in diff --git a/.github/workflows/flutter.yml b/.github/workflows/flutter.yml deleted file mode 100644 index 80de7de..0000000 --- a/.github/workflows/flutter.yml +++ /dev/null @@ -1,27 +0,0 @@ -name: CI - -on: - push: - branches: [ master ] - pull_request: - -jobs: - lint: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - - uses: actions/cache@v3 - with: - path: | - ~/.gradle/wrapper - /opt/hostedtoolcache/flutter - key: ${{ runner.OS }}-flutter-install-cache - - uses: subosito/flutter-action@v2 - with: - channel: 'stable' - - name: Flutter pub get - run: flutter pub get - - name: Flutter format - run: dart format -o none --set-exit-if-changed . - - name: Flutter analyze - run: flutter analyze diff --git a/CHANGELOG.md b/CHANGELOG.md index 89b5f95..e850c81 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,6 @@ +## 5.1.1 +* Added Ci and linter + ## 5.1.0 * Added the option to disable the showPassword button on the passwordfield. diff --git a/analysis_options.yaml b/analysis_options.yaml index a5744c1..31b4b51 100644 --- a/analysis_options.yaml +++ b/analysis_options.yaml @@ -1,4 +1,9 @@ -include: package:flutter_lints/flutter.yaml +include: package:flutter_iconica_analysis/analysis_options.yaml -# Additional information about this file can be found at -# https://dart.dev/guides/language/analysis-options +# Possible to overwrite the rules from the package + +analyzer: + exclude: + +linter: + rules: diff --git a/lib/flutter_login.dart b/lib/flutter_login.dart index 6a862eb..94185e6 100644 --- a/lib/flutter_login.dart +++ b/lib/flutter_login.dart @@ -1,9 +1,10 @@ +/// library flutter_login; -export 'src/config/spacer_options.dart'; export 'src/config/login_options.dart'; +export 'src/config/spacer_options.dart'; +export 'src/service/login_validation.dart'; +export 'src/service/validation.dart'; export 'src/widgets/email_password_login.dart'; export 'src/widgets/forgot_password_form.dart'; -export 'src/service/validation.dart'; -export 'src/service/login_validation.dart'; export 'src/widgets/mfa_widget.dart'; diff --git a/lib/src/config/login_options.dart b/lib/src/config/login_options.dart index a9e9c6f..416c215 100644 --- a/lib/src/config/login_options.dart +++ b/lib/src/config/login_options.dart @@ -42,7 +42,8 @@ class LoginOptions { final Widget? title; final Widget? subtitle; - /// Option to modify the spacing between the title, subtitle, image, form, and button. + /// Option to modify the spacing between the title, subtitle, image, form, + /// and button. final LoginSpacerOptions spacers; /// Maximum width of the form. Defaults to 400. @@ -98,15 +99,14 @@ Widget _createLoginButton( bool disabled, OptionalAsyncCallback onDisabledPress, LoginOptions options, -) { - return Opacity( - opacity: disabled ? 0.5 : 1.0, - child: ElevatedButton( - onPressed: !disabled ? onPressed : onDisabledPress, - child: Text(options.translations.loginButton), - ), - ); -} +) => + Opacity( + opacity: disabled ? 0.5 : 1.0, + child: ElevatedButton( + onPressed: !disabled ? onPressed : onDisabledPress, + child: Text(options.translations.loginButton), + ), + ); Widget _createForgotPasswordButton( BuildContext context, @@ -114,15 +114,14 @@ Widget _createForgotPasswordButton( bool disabled, OptionalAsyncCallback onDisabledPress, LoginOptions options, -) { - return Opacity( - opacity: disabled ? 0.5 : 1.0, - child: ElevatedButton( - onPressed: !disabled ? onPressed : onDisabledPress, - child: Text(options.translations.forgotPasswordButton), - ), - ); -} +) => + Opacity( + opacity: disabled ? 0.5 : 1.0, + child: ElevatedButton( + onPressed: !disabled ? onPressed : onDisabledPress, + child: Text(options.translations.forgotPasswordButton), + ), + ); Widget _createRequestForgotPasswordButton( BuildContext context, @@ -130,15 +129,14 @@ Widget _createRequestForgotPasswordButton( bool disabled, OptionalAsyncCallback onDisabledPress, LoginOptions options, -) { - return Opacity( - opacity: disabled ? 0.5 : 1.0, - child: ElevatedButton( - onPressed: !disabled ? onPressed : onDisabledPress, - child: Text(options.translations.requestForgotPasswordButton), - ), - ); -} +) => + Opacity( + opacity: disabled ? 0.5 : 1.0, + child: ElevatedButton( + onPressed: !disabled ? onPressed : onDisabledPress, + child: Text(options.translations.requestForgotPasswordButton), + ), + ); Widget _createRegisterButton( BuildContext context, @@ -146,19 +144,19 @@ Widget _createRegisterButton( bool disabled, OptionalAsyncCallback onDisabledPress, LoginOptions options, -) { - return Opacity( - opacity: disabled ? 0.5 : 1.0, - child: ElevatedButton( - onPressed: !disabled ? onPressed : onDisabledPress, - child: Text(options.translations.registrationButton), - ), - ); -} +) => + Opacity( + opacity: disabled ? 0.5 : 1.0, + child: ElevatedButton( + onPressed: !disabled ? onPressed : onDisabledPress, + child: Text(options.translations.registrationButton), + ), + ); typedef ButtonBuilder = Widget Function( BuildContext context, OptionalAsyncCallback onPressed, + // ignore: avoid_positional_boolean_parameters bool isDisabled, OptionalAsyncCallback onDisabledPress, LoginOptions options, diff --git a/lib/src/config/spacer_options.dart b/lib/src/config/spacer_options.dart index ceb6ec9..8c33aa0 100644 --- a/lib/src/config/spacer_options.dart +++ b/lib/src/config/spacer_options.dart @@ -30,6 +30,7 @@ class LoginSpacerOptions { /// Flex value for the spacer after the button. final int? spacerAfterButton; - /// Flex value for the form. Defaults to 1. Use this when also using the other spacer options. + /// Flex value for the form. Defaults to 1. Use this when also using the + /// other spacer options. final int formFlexValue; } diff --git a/lib/src/service/login_validation.dart b/lib/src/service/login_validation.dart index e0b51f3..f5e3216 100644 --- a/lib/src/service/login_validation.dart +++ b/lib/src/service/login_validation.dart @@ -11,8 +11,8 @@ class LoginValidationService implements ValidationService { return options.translations.emailEmpty; } if (!RegExp( - r"""(?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*|"(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])*")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\[(?:(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9]))\.){3}(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9])|[a-z0-9-]*[a-z0-9]:(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21-\x5a\x53-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])+)\])""") - .hasMatch(value)) { + r"""(?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*|"(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])*")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\[(?:(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9]))\.){3}(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9])|[a-z0-9-]*[a-z0-9]:(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21-\x5a\x53-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])+)\])""", + ).hasMatch(value)) { return options.translations.emailInvalid; } return null; diff --git a/lib/src/widgets/email_password_login.dart b/lib/src/widgets/email_password_login.dart index b08c1a3..3af36de 100644 --- a/lib/src/widgets/email_password_login.dart +++ b/lib/src/widgets/email_password_login.dart @@ -5,9 +5,9 @@ import 'package:flutter_login/flutter_login.dart'; class EmailPasswordLoginForm extends StatefulWidget { const EmailPasswordLoginForm({ + required this.onLogin, super.key, this.onForgotPassword, - required this.onLogin, this.onRegister, this.options = const LoginOptions(), }); @@ -40,7 +40,7 @@ class _EmailPasswordLoginFormState extends State { } void _validate() { - late bool isValid = + late var isValid = widget.options.validations.validateEmail(_currentEmail) == null && widget.options.validations.validatePassword(_currentPassword) == null; @@ -96,7 +96,7 @@ class _EmailPasswordLoginFormState extends State { options.title, theme.textTheme.headlineSmall, ), - ) + ), ], if (options.spacers.spacerAfterTitle != null) ...[ Spacer(flex: options.spacers.spacerAfterTitle!), @@ -111,7 +111,7 @@ class _EmailPasswordLoginFormState extends State { options.subtitle, theme.textTheme.titleSmall, ), - ) + ), ], if (options.spacers.spacerAfterSubtitle != null) ...[ Spacer(flex: options.spacers.spacerAfterSubtitle!), @@ -159,7 +159,7 @@ class _EmailPasswordLoginFormState extends State { keyboardType: TextInputType.visiblePassword, textInputAction: TextInputAction.done, style: options.passwordTextStyle, - onFieldSubmitted: (_) => _handleLogin(), + onFieldSubmitted: (_) async => _handleLogin(), decoration: options.passwordDecoration.copyWith( suffixIcon: options.showObscurePassword ? IconButton( @@ -199,22 +199,20 @@ class _EmailPasswordLoginFormState extends State { const SizedBox(height: 8), AnimatedBuilder( animation: _formValid, - builder: (context, _) { - return options.loginButtonBuilder( - context, - _handleLogin, - !_formValid.value, - () { - _formKey.currentState?.validate(); - }, - options, - ); - }, + builder: (context, _) => options.loginButtonBuilder( + context, + _handleLogin, + !_formValid.value, + () { + _formKey.currentState?.validate(); + }, + options, + ), ), if (widget.onRegister != null) ...[ options.registrationButtonBuilder( context, - () { + () async { widget.onRegister?.call( _currentEmail, _currentPassword, diff --git a/lib/src/widgets/forgot_password_form.dart b/lib/src/widgets/forgot_password_form.dart index 318fedb..177376a 100644 --- a/lib/src/widgets/forgot_password_form.dart +++ b/lib/src/widgets/forgot_password_form.dart @@ -5,10 +5,10 @@ import 'package:flutter_login/flutter_login.dart'; class ForgotPasswordForm extends StatefulWidget { const ForgotPasswordForm({ - super.key, required this.options, required this.description, required this.onRequestForgotPassword, + super.key, this.title, }); @@ -50,7 +50,7 @@ class _ForgotPasswordFormState extends State { } void _validate() { - late bool isValid = + late var isValid = widget.options.validations.validateEmail(_currentEmail) == null; if (isValid != _formValid.value) { _formValid.value = isValid; @@ -99,24 +99,22 @@ class _ForgotPasswordFormState extends State { ), AnimatedBuilder( animation: _formValid, - builder: (context, snapshot) { - return Align( - child: widget.options.requestForgotPasswordButtonBuilder( - context, - () { - _formKey.currentState?.validate(); - if (_formValid.value) { - widget.onRequestForgotPassword(_currentEmail); - } - }, - !_formValid.value, - () { - _formKey.currentState?.validate(); - }, - options, - ), - ); - }, + builder: (context, snapshot) => Align( + child: widget.options.requestForgotPasswordButtonBuilder( + context, + () async { + _formKey.currentState?.validate(); + if (_formValid.value) { + widget.onRequestForgotPassword(_currentEmail); + } + }, + !_formValid.value, + () { + _formKey.currentState?.validate(); + }, + options, + ), + ), ), ], ), diff --git a/lib/src/widgets/mfa_widget.dart b/lib/src/widgets/mfa_widget.dart index 661b6a1..38341d1 100644 --- a/lib/src/widgets/mfa_widget.dart +++ b/lib/src/widgets/mfa_widget.dart @@ -22,6 +22,8 @@ class MFAWidget extends StatefulWidget { }) : assert( (onSubmitted == null && submitButtonBuilder == null) || (onSubmitted != null && submitButtonBuilder != null), + 'onSubmitted and submitButtonBuilder must be both null or both' + ' not null', ); final Function(String code) onCompleted; @@ -48,35 +50,33 @@ class _MFAWidgetState extends State { final TextEditingController _controller = TextEditingController(); @override - Widget build(BuildContext context) { - return Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Pinput( - defaultPinTheme: widget.defaultPinTheme, - focusedPinTheme: widget.focusedPinTheme, - submittedPinTheme: widget.submittedPinTheme, - followingPinTheme: widget.followingPinTheme, - disabledPinTheme: widget.disabledPinTheme, - errorPinTheme: widget.errorPinTheme, - separatorPositions: widget.seperatorPositions, - errorBuilder: widget.errorBuilder, - errorText: widget.errorText, - errorTextStyle: widget.errorTextStyle, - validator: widget.validator, - controller: _controller, - length: widget.length, - onCompleted: (_) { - widget.onCompleted(_controller.text); - }, - ), - if (widget.onSubmitted != null && - widget.submitButtonBuilder != null) ...[ - widget.submitButtonBuilder!(() { - widget.onSubmitted!(_controller.text); - }), + Widget build(BuildContext context) => Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Pinput( + defaultPinTheme: widget.defaultPinTheme, + focusedPinTheme: widget.focusedPinTheme, + submittedPinTheme: widget.submittedPinTheme, + followingPinTheme: widget.followingPinTheme, + disabledPinTheme: widget.disabledPinTheme, + errorPinTheme: widget.errorPinTheme, + separatorPositions: widget.seperatorPositions, + errorBuilder: widget.errorBuilder, + errorText: widget.errorText, + errorTextStyle: widget.errorTextStyle, + validator: widget.validator, + controller: _controller, + length: widget.length, + onCompleted: (_) { + widget.onCompleted(_controller.text); + }, + ), + if (widget.onSubmitted != null && + widget.submitButtonBuilder != null) ...[ + widget.submitButtonBuilder!(() { + widget.onSubmitted!(_controller.text); + }), + ], ], - ], - ); - } + ); } diff --git a/pubspec.yaml b/pubspec.yaml index 63ecbfb..dffa4ce 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,6 +1,6 @@ name: flutter_login description: Flutter Login Component -version: 5.1.0 +version: 5.1.1 environment: sdk: ">=2.18.1 <3.0.0" @@ -14,6 +14,9 @@ dependencies: dev_dependencies: flutter_test: sdk: flutter - flutter_lints: ^2.0.0 + flutter_iconica_analysis: + git: + url: https://github.com/Iconica-Development/flutter_iconica_analysis + ref: 6.0.0 flutter: