Merge pull request #10 from Iconica-Development/feature/Improve_README

Updated README, added GIF, added Github Actions, fixed overflow bug w…
This commit is contained in:
FlutterJoey 2022-12-02 15:40:19 +01:00 committed by GitHub
commit badffe9538
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 198 additions and 143 deletions

32
.github/workflows/flutter.yml vendored Normal file
View file

@ -0,0 +1,32 @@
name: CI
on:
push:
branches: [ master ]
pull_request:
branches:
- master
- feature/*
- bugfix/*
- hotfix/*
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: flutter format -o none --set-exit-if-changed .
- name: Flutter analyze
run: flutter analyze

View file

@ -1,21 +1,15 @@
[![pub package](https://img.shields.io/pub/v/flutter_introduction_widget.svg)](https://github.com/Iconica-Development) [![Build status](https://img.shields.io/github/workflow/status/Iconica-Development/flutter_login_widget/CI)](https://github.com/Iconica-Development/flutter_login_widget/actions/new) [![style: effective dart](https://img.shields.io/badge/style-effective_dart-40c4ff.svg)](https://github.com/tenhobi/effective_dart)
# Login Widget
A package facilitating the basic ingredients for creating functional yet customizable login pages A package facilitating the basic ingredients for creating functional yet customizable login pages
## Features [Login GIF](flutter_login.gif)
Create a login screen for email and password logins ## Setup
Create a forgot password screen by passing in the email from the login
## Getting started To use this package, add `flutter_login_widget` as a dependency in your pubspec.yaml file.
1. install the package by adding the following to your pubspec.yaml ## How to use
```
flutter_login:
git:
url: https://github.com/Iconica-Development/flutter_login.git
ref: 1.0.0
```
## Usage
```dart ```dart
final loginOptions = LoginOptions( final loginOptions = LoginOptions(
@ -93,3 +87,17 @@ class ForgotPasswordScreen extends StatelessWidget {
} }
``` ```
See the [Example Code](example/lib/main.dart) for an example on how to use this package.
## Issues
Please file any issues, bugs or feature request as an issue on our [GitHub](https://github.com/Iconica-Development/flutter_login_widget) page. Commercial support is available if you need help with integration with your app or services. You can contact us at [support@iconica.nl](mailto:support@iconica.nl).
## Want to contribute
If you would like to contribute to the plugin (e.g. by improving the documentation, solving a bug or adding a cool new feature), please carefully review our [contribution guide](./CONTRIBUTING.md) and send us your [pull request](https://github.com/Iconica-Development/flutter_login_widget/pulls).
## Author
This `flutter_login_widget` for Flutter is developed by [Iconica](https://iconica.nl). You can contact us at <support@iconica.nl>

View file

@ -9,8 +9,10 @@ final loginOptions = LoginOptions(
), ),
emailInputPrefix: const Icon(Icons.email), emailInputPrefix: const Icon(Icons.email),
passwordInputPrefix: const Icon(Icons.password), passwordInputPrefix: const Icon(Icons.password),
title: const Text('Login'), title: const Text('Login Demo'),
image: const FlutterLogo(), image: const FlutterLogo(
size: 200,
),
requestForgotPasswordButtonBuilder: ( requestForgotPasswordButtonBuilder: (
context, context,
onPressed, onPressed,

BIN
flutter_login.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3 MiB

View file

@ -65,140 +65,153 @@ class _EmailPasswordLoginFormState extends State<EmailPasswordLoginForm> {
Widget build(BuildContext context) { Widget build(BuildContext context) {
var theme = Theme.of(context); var theme = Theme.of(context);
var options = widget.options; var options = widget.options;
return Column( return CustomScrollView(
children: [ physics: MediaQuery.of(context).viewInsets.bottom == 0
if (options.title != null) ...[ ? const NeverScrollableScrollPhysics()
const SizedBox( : null,
height: 60, slivers: [
), SliverFillRemaining(
Align( fillOverscroll: true,
alignment: Alignment.topCenter, hasScrollBody: false,
child: _wrapWithDefaultStyle( child: Column(
options.title, children: [
theme.textTheme.headline6, if (options.title != null) ...[
), const SizedBox(
) height: 60,
], ),
if (options.subtitle != null) ...[ Align(
const SizedBox( alignment: Alignment.topCenter,
height: 10, child: _wrapWithDefaultStyle(
), options.title,
Align( theme.textTheme.headline6,
alignment: Alignment.topCenter, ),
child: _wrapWithDefaultStyle( )
options.subtitle, ],
theme.textTheme.subtitle1, if (options.subtitle != null) ...[
), const SizedBox(
) height: 10,
], ),
if (options.image != null) ...[ Align(
Padding( alignment: Alignment.topCenter,
padding: const EdgeInsets.all(16), child: _wrapWithDefaultStyle(
child: options.image, options.subtitle,
), theme.textTheme.subtitle1,
], ),
Expanded( )
child: ConstrainedBox( ],
constraints: const BoxConstraints( if (options.image != null) ...[
maxWidth: 300, Padding(
), padding: const EdgeInsets.all(16),
child: Form( child: options.image,
key: _formKey, ),
child: Align( ],
child: Column( Expanded(
mainAxisSize: MainAxisSize.min, child: ConstrainedBox(
children: [ constraints: const BoxConstraints(
options.emailInputContainerBuilder( maxWidth: 300,
TextFormField( ),
onChanged: _updateCurrentEmail, child: Form(
validator: widget.options.validations.validateEmail, key: _formKey,
initialValue: options.initialEmail, child: Align(
keyboardType: TextInputType.emailAddress, child: Column(
textInputAction: TextInputAction.next, mainAxisSize: MainAxisSize.min,
decoration: options.decoration.copyWith( children: [
hintText: options.emailHintText, options.emailInputContainerBuilder(
prefixIcon: options.emailInputPrefix, TextFormField(
label: options.emailLabel, onChanged: _updateCurrentEmail,
), validator:
), widget.options.validations.validateEmail,
), initialValue: options.initialEmail,
const SizedBox(height: 24), keyboardType: TextInputType.emailAddress,
options.passwordInputContainerBuilder( textInputAction: TextInputAction.next,
TextFormField( decoration: options.decoration.copyWith(
obscureText: _obscurePassword, hintText: options.emailHintText,
onChanged: _updateCurrentPassword, prefixIcon: options.emailInputPrefix,
validator: widget.options.validations.validatePassword, label: options.emailLabel,
initialValue: options.initialPassword, ),
keyboardType: TextInputType.visiblePassword,
textInputAction: TextInputAction.done,
onFieldSubmitted: (_) => _handleLogin(),
decoration: options.decoration.copyWith(
hintText: options.passwordHintText,
label: options.passwordLabel,
prefixIcon: options.passwordInputPrefix,
suffixIcon: IconButton(
onPressed: () {
setState(() {
_obscurePassword = !_obscurePassword;
});
},
icon: Icon(
_obscurePassword
? Icons.visibility
: Icons.visibility_off,
), ),
), ),
), const SizedBox(height: 24),
options.passwordInputContainerBuilder(
TextFormField(
obscureText: _obscurePassword,
onChanged: _updateCurrentPassword,
validator:
widget.options.validations.validatePassword,
initialValue: options.initialPassword,
keyboardType: TextInputType.visiblePassword,
textInputAction: TextInputAction.done,
onFieldSubmitted: (_) => _handleLogin(),
decoration: options.decoration.copyWith(
hintText: options.passwordHintText,
label: options.passwordLabel,
prefixIcon: options.passwordInputPrefix,
suffixIcon: IconButton(
onPressed: () {
setState(() {
_obscurePassword = !_obscurePassword;
});
},
icon: Icon(
_obscurePassword
? Icons.visibility
: Icons.visibility_off,
),
),
),
),
),
const SizedBox(height: 24),
if (widget.onForgotPassword != null) ...[
Align(
alignment: Alignment.topRight,
child: options.forgotPasswordButtonBuilder(
context,
() {
widget.onForgotPassword?.call(_currentEmail);
},
false,
() {},
options,
),
),
],
const SizedBox(height: 8),
AnimatedBuilder(
animation: _formValid,
builder: (context, _) {
return options.loginButtonBuilder(
context,
_handleLogin,
!_formValid.value,
() {
_formKey.currentState?.validate();
},
options,
);
},
),
if (widget.onRegister != null) ...[
options.registrationButtonBuilder(
context,
() {
widget.onRegister?.call(
_currentEmail,
_currentPassword,
);
},
false,
() {},
options,
),
]
],
), ),
), ),
const SizedBox(height: 24), ),
if (widget.onForgotPassword != null) ...[
Align(
alignment: Alignment.topRight,
child: options.forgotPasswordButtonBuilder(
context,
() {
widget.onForgotPassword?.call(_currentEmail);
},
false,
() {},
options,
),
),
],
const SizedBox(height: 8),
AnimatedBuilder(
animation: _formValid,
builder: (context, _) {
return options.loginButtonBuilder(
context,
_handleLogin,
!_formValid.value,
() {
_formKey.currentState?.validate();
},
options,
);
},
),
if (widget.onRegister != null) ...[
options.registrationButtonBuilder(
context,
() {
widget.onRegister?.call(
_currentEmail,
_currentPassword,
);
},
false,
() {},
options,
),
]
],
), ),
), ),
), ],
), ),
), ),
], ],