fix: added Ci and linter

This commit is contained in:
mike doornenbal 2024-02-06 16:05:46 +01:00
parent 15886ed5c3
commit b1d379b321
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
* 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
# https://dart.dev/guides/language/analysis-options
# Possible to overwrite the rules from the package
analyzer:
exclude:
linter:
rules:

View file

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

View file

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

View file

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

View file

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

View file

@ -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<EmailPasswordLoginForm> {
}
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<EmailPasswordLoginForm> {
options.title,
theme.textTheme.headlineSmall,
),
)
),
],
if (options.spacers.spacerAfterTitle != null) ...[
Spacer(flex: options.spacers.spacerAfterTitle!),
@ -111,7 +111,7 @@ class _EmailPasswordLoginFormState extends State<EmailPasswordLoginForm> {
options.subtitle,
theme.textTheme.titleSmall,
),
)
),
],
if (options.spacers.spacerAfterSubtitle != null) ...[
Spacer(flex: options.spacers.spacerAfterSubtitle!),
@ -159,7 +159,7 @@ class _EmailPasswordLoginFormState extends State<EmailPasswordLoginForm> {
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<EmailPasswordLoginForm> {
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,

View file

@ -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<ForgotPasswordForm> {
}
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<ForgotPasswordForm> {
),
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,
),
),
),
],
),

View file

@ -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<MFAWidget> {
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);
}),
],
],
],
);
}
);
}

View file

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