mirror of
https://github.com/Iconica-Development/flutter_login_widget.git
synced 2025-05-19 13:43:44 +02:00
fix: added Ci and linter
This commit is contained in:
parent
15886ed5c3
commit
b1d379b321
12 changed files with 136 additions and 142 deletions
14
.github/workflows/component-ci.yml
vendored
Normal file
14
.github/workflows/component-ci.yml
vendored
Normal 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
|
27
.github/workflows/flutter.yml
vendored
27
.github/workflows/flutter.yml
vendored
|
@ -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
|
|
|
@ -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.
|
||||||
|
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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';
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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,
|
||||||
),
|
),
|
||||||
);
|
),
|
||||||
},
|
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
|
|
@ -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(
|
||||||
|
@ -78,5 +79,4 @@ class _MFAWidgetState extends State<MFAWidget> {
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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:
|
||||||
|
|
Loading…
Reference in a new issue