Merge branch 'fix/add_ci_linter'

This commit is contained in:
mike doornenbal 2024-02-07 10:03:25 +01:00
commit 4b29d92ce0
12 changed files with 136 additions and 142 deletions

14
.github/workflows/component-ci.yml vendored Normal file
View file

@ -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

View file

@ -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

View file

@ -1,3 +1,6 @@
## 5.1.1
* Added Ci and linter
## 5.1.0 ## 5.1.0
* Added the option to disable the showPassword button on the passwordfield. * Added the option to disable the showPassword button on the passwordfield.

View file

@ -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 # Possible to overwrite the rules from the package
# https://dart.dev/guides/language/analysis-options
analyzer:
exclude:
linter:
rules:

View file

@ -1,9 +1,10 @@
///
library flutter_login; library flutter_login;
export 'src/config/spacer_options.dart';
export 'src/config/login_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/email_password_login.dart';
export 'src/widgets/forgot_password_form.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'; export 'src/widgets/mfa_widget.dart';

View file

@ -42,7 +42,8 @@ class LoginOptions {
final Widget? title; final Widget? title;
final Widget? subtitle; 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; final LoginSpacerOptions spacers;
/// Maximum width of the form. Defaults to 400. /// Maximum width of the form. Defaults to 400.
@ -98,15 +99,14 @@ Widget _createLoginButton(
bool disabled, bool disabled,
OptionalAsyncCallback onDisabledPress, OptionalAsyncCallback onDisabledPress,
LoginOptions options, LoginOptions options,
) { ) =>
return Opacity( Opacity(
opacity: disabled ? 0.5 : 1.0, opacity: disabled ? 0.5 : 1.0,
child: ElevatedButton( child: ElevatedButton(
onPressed: !disabled ? onPressed : onDisabledPress, onPressed: !disabled ? onPressed : onDisabledPress,
child: Text(options.translations.loginButton), child: Text(options.translations.loginButton),
), ),
); );
}
Widget _createForgotPasswordButton( Widget _createForgotPasswordButton(
BuildContext context, BuildContext context,
@ -114,15 +114,14 @@ Widget _createForgotPasswordButton(
bool disabled, bool disabled,
OptionalAsyncCallback onDisabledPress, OptionalAsyncCallback onDisabledPress,
LoginOptions options, LoginOptions options,
) { ) =>
return Opacity( Opacity(
opacity: disabled ? 0.5 : 1.0, opacity: disabled ? 0.5 : 1.0,
child: ElevatedButton( child: ElevatedButton(
onPressed: !disabled ? onPressed : onDisabledPress, onPressed: !disabled ? onPressed : onDisabledPress,
child: Text(options.translations.forgotPasswordButton), child: Text(options.translations.forgotPasswordButton),
), ),
); );
}
Widget _createRequestForgotPasswordButton( Widget _createRequestForgotPasswordButton(
BuildContext context, BuildContext context,
@ -130,15 +129,14 @@ Widget _createRequestForgotPasswordButton(
bool disabled, bool disabled,
OptionalAsyncCallback onDisabledPress, OptionalAsyncCallback onDisabledPress,
LoginOptions options, LoginOptions options,
) { ) =>
return Opacity( Opacity(
opacity: disabled ? 0.5 : 1.0, opacity: disabled ? 0.5 : 1.0,
child: ElevatedButton( child: ElevatedButton(
onPressed: !disabled ? onPressed : onDisabledPress, onPressed: !disabled ? onPressed : onDisabledPress,
child: Text(options.translations.requestForgotPasswordButton), child: Text(options.translations.requestForgotPasswordButton),
), ),
); );
}
Widget _createRegisterButton( Widget _createRegisterButton(
BuildContext context, BuildContext context,
@ -146,19 +144,19 @@ Widget _createRegisterButton(
bool disabled, bool disabled,
OptionalAsyncCallback onDisabledPress, OptionalAsyncCallback onDisabledPress,
LoginOptions options, LoginOptions options,
) { ) =>
return Opacity( Opacity(
opacity: disabled ? 0.5 : 1.0, opacity: disabled ? 0.5 : 1.0,
child: ElevatedButton( child: ElevatedButton(
onPressed: !disabled ? onPressed : onDisabledPress, onPressed: !disabled ? onPressed : onDisabledPress,
child: Text(options.translations.registrationButton), child: Text(options.translations.registrationButton),
), ),
); );
}
typedef ButtonBuilder = Widget Function( typedef ButtonBuilder = Widget Function(
BuildContext context, BuildContext context,
OptionalAsyncCallback onPressed, OptionalAsyncCallback onPressed,
// ignore: avoid_positional_boolean_parameters
bool isDisabled, bool isDisabled,
OptionalAsyncCallback onDisabledPress, OptionalAsyncCallback onDisabledPress,
LoginOptions options, LoginOptions options,

View file

@ -30,6 +30,7 @@ class LoginSpacerOptions {
/// Flex value for the spacer after the button. /// Flex value for the spacer after the button.
final int? spacerAfterButton; 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; final int formFlexValue;
} }

View file

@ -11,8 +11,8 @@ class LoginValidationService implements ValidationService {
return options.translations.emailEmpty; return options.translations.emailEmpty;
} }
if (!RegExp( 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])+)\])""") 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)) { ).hasMatch(value)) {
return options.translations.emailInvalid; return options.translations.emailInvalid;
} }
return null; return null;

View file

@ -5,9 +5,9 @@ import 'package:flutter_login/flutter_login.dart';
class EmailPasswordLoginForm extends StatefulWidget { class EmailPasswordLoginForm extends StatefulWidget {
const EmailPasswordLoginForm({ const EmailPasswordLoginForm({
required this.onLogin,
super.key, super.key,
this.onForgotPassword, this.onForgotPassword,
required this.onLogin,
this.onRegister, this.onRegister,
this.options = const LoginOptions(), this.options = const LoginOptions(),
}); });
@ -40,7 +40,7 @@ class _EmailPasswordLoginFormState extends State<EmailPasswordLoginForm> {
} }
void _validate() { void _validate() {
late bool isValid = late var isValid =
widget.options.validations.validateEmail(_currentEmail) == null && widget.options.validations.validateEmail(_currentEmail) == null &&
widget.options.validations.validatePassword(_currentPassword) == widget.options.validations.validatePassword(_currentPassword) ==
null; null;
@ -96,7 +96,7 @@ class _EmailPasswordLoginFormState extends State<EmailPasswordLoginForm> {
options.title, options.title,
theme.textTheme.headlineSmall, theme.textTheme.headlineSmall,
), ),
) ),
], ],
if (options.spacers.spacerAfterTitle != null) ...[ if (options.spacers.spacerAfterTitle != null) ...[
Spacer(flex: options.spacers.spacerAfterTitle!), Spacer(flex: options.spacers.spacerAfterTitle!),
@ -111,7 +111,7 @@ class _EmailPasswordLoginFormState extends State<EmailPasswordLoginForm> {
options.subtitle, options.subtitle,
theme.textTheme.titleSmall, theme.textTheme.titleSmall,
), ),
) ),
], ],
if (options.spacers.spacerAfterSubtitle != null) ...[ if (options.spacers.spacerAfterSubtitle != null) ...[
Spacer(flex: options.spacers.spacerAfterSubtitle!), Spacer(flex: options.spacers.spacerAfterSubtitle!),
@ -159,7 +159,7 @@ class _EmailPasswordLoginFormState extends State<EmailPasswordLoginForm> {
keyboardType: TextInputType.visiblePassword, keyboardType: TextInputType.visiblePassword,
textInputAction: TextInputAction.done, textInputAction: TextInputAction.done,
style: options.passwordTextStyle, style: options.passwordTextStyle,
onFieldSubmitted: (_) => _handleLogin(), onFieldSubmitted: (_) async => _handleLogin(),
decoration: options.passwordDecoration.copyWith( decoration: options.passwordDecoration.copyWith(
suffixIcon: options.showObscurePassword suffixIcon: options.showObscurePassword
? IconButton( ? IconButton(
@ -199,8 +199,7 @@ class _EmailPasswordLoginFormState extends State<EmailPasswordLoginForm> {
const SizedBox(height: 8), const SizedBox(height: 8),
AnimatedBuilder( AnimatedBuilder(
animation: _formValid, animation: _formValid,
builder: (context, _) { builder: (context, _) => options.loginButtonBuilder(
return options.loginButtonBuilder(
context, context,
_handleLogin, _handleLogin,
!_formValid.value, !_formValid.value,
@ -208,13 +207,12 @@ class _EmailPasswordLoginFormState extends State<EmailPasswordLoginForm> {
_formKey.currentState?.validate(); _formKey.currentState?.validate();
}, },
options, options,
); ),
},
), ),
if (widget.onRegister != null) ...[ if (widget.onRegister != null) ...[
options.registrationButtonBuilder( options.registrationButtonBuilder(
context, context,
() { () async {
widget.onRegister?.call( widget.onRegister?.call(
_currentEmail, _currentEmail,
_currentPassword, _currentPassword,

View file

@ -5,10 +5,10 @@ import 'package:flutter_login/flutter_login.dart';
class ForgotPasswordForm extends StatefulWidget { class ForgotPasswordForm extends StatefulWidget {
const ForgotPasswordForm({ const ForgotPasswordForm({
super.key,
required this.options, required this.options,
required this.description, required this.description,
required this.onRequestForgotPassword, required this.onRequestForgotPassword,
super.key,
this.title, this.title,
}); });
@ -50,7 +50,7 @@ class _ForgotPasswordFormState extends State<ForgotPasswordForm> {
} }
void _validate() { void _validate() {
late bool isValid = late var isValid =
widget.options.validations.validateEmail(_currentEmail) == null; widget.options.validations.validateEmail(_currentEmail) == null;
if (isValid != _formValid.value) { if (isValid != _formValid.value) {
_formValid.value = isValid; _formValid.value = isValid;
@ -99,11 +99,10 @@ class _ForgotPasswordFormState extends State<ForgotPasswordForm> {
), ),
AnimatedBuilder( AnimatedBuilder(
animation: _formValid, animation: _formValid,
builder: (context, snapshot) { builder: (context, snapshot) => Align(
return Align(
child: widget.options.requestForgotPasswordButtonBuilder( child: widget.options.requestForgotPasswordButtonBuilder(
context, context,
() { () async {
_formKey.currentState?.validate(); _formKey.currentState?.validate();
if (_formValid.value) { if (_formValid.value) {
widget.onRequestForgotPassword(_currentEmail); widget.onRequestForgotPassword(_currentEmail);
@ -115,8 +114,7 @@ class _ForgotPasswordFormState extends State<ForgotPasswordForm> {
}, },
options, options,
), ),
); ),
},
), ),
], ],
), ),

View file

@ -22,6 +22,8 @@ class MFAWidget extends StatefulWidget {
}) : assert( }) : assert(
(onSubmitted == null && submitButtonBuilder == null) || (onSubmitted == null && submitButtonBuilder == null) ||
(onSubmitted != null && submitButtonBuilder != null), (onSubmitted != null && submitButtonBuilder != null),
'onSubmitted and submitButtonBuilder must be both null or both'
' not null',
); );
final Function(String code) onCompleted; final Function(String code) onCompleted;
@ -48,8 +50,7 @@ class _MFAWidgetState extends State<MFAWidget> {
final TextEditingController _controller = TextEditingController(); final TextEditingController _controller = TextEditingController();
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) => Column(
return Column(
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
children: [ children: [
Pinput( Pinput(
@ -79,4 +80,3 @@ class _MFAWidgetState extends State<MFAWidget> {
], ],
); );
} }
}

View file

@ -1,6 +1,6 @@
name: flutter_login name: flutter_login
description: Flutter Login Component description: Flutter Login Component
version: 5.1.0 version: 5.1.1
environment: environment:
sdk: ">=2.18.1 <3.0.0" sdk: ">=2.18.1 <3.0.0"
@ -14,6 +14,9 @@ dependencies:
dev_dependencies: dev_dependencies:
flutter_test: flutter_test:
sdk: flutter 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: flutter: