mirror of
https://github.com/Iconica-Development/flutter_profile.git
synced 2025-05-19 01:03:45 +02:00
Merge pull request #28 from Iconica-Development/feat/change_password_current_password
feat: Add password field for authentication
This commit is contained in:
commit
802265e43c
13 changed files with 194 additions and 140 deletions
|
@ -1,3 +1,7 @@
|
||||||
|
## 1.3.0
|
||||||
|
|
||||||
|
- Field has been added so the user can provide it's current password for reauthentication.
|
||||||
|
|
||||||
## 1.2.1
|
## 1.2.1
|
||||||
|
|
||||||
- Added Iconica CI and Iconica Linter
|
- Added Iconica CI and Iconica Linter
|
||||||
|
|
|
@ -52,62 +52,67 @@ class _ProfileExampleState extends State<ProfileExample> {
|
||||||
var width = MediaQuery.of(context).size.width;
|
var width = MediaQuery.of(context).size.width;
|
||||||
|
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
body: Center(
|
body: ProfilePage(
|
||||||
child: ProfilePage(
|
changePasswordConfig:
|
||||||
changePasswordConfig:
|
const ChangePasswordConfig(enablePasswordChange: true),
|
||||||
const ChangePasswordConfig(enablePasswordChange: true),
|
wrapViewOptions: WrapViewOptions(
|
||||||
wrapViewOptions: WrapViewOptions(
|
spacing: 8,
|
||||||
direction: Axis.horizontal,
|
direction: Axis.vertical,
|
||||||
spacing: 16,
|
),
|
||||||
),
|
bottomActionText: 'Log out',
|
||||||
bottomActionText: 'Log out',
|
itemBuilderOptions: ItemBuilderOptions(
|
||||||
itemBuilderOptions: ItemBuilderOptions(
|
//no label for email
|
||||||
//no label for email
|
validators: {
|
||||||
validators: {
|
'first_name': (String? value) {
|
||||||
'first_name': (String? value) {
|
if (value == null || value.isEmpty) {
|
||||||
if (value == null || value.isEmpty) {
|
return 'Field empty';
|
||||||
return 'Field empty';
|
}
|
||||||
}
|
return null;
|
||||||
return null;
|
|
||||||
},
|
|
||||||
'last_name': (String? value) {
|
|
||||||
if (value == null || value.isEmpty) {
|
|
||||||
return 'Field empty';
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
},
|
|
||||||
'email': (String? value) {
|
|
||||||
if (value == null || value.isEmpty) {
|
|
||||||
return 'Field empty';
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
inputDecorationField: {
|
'last_name': (String? value) {
|
||||||
'password_1': const InputDecoration(
|
if (value == null || value.isEmpty) {
|
||||||
|
return 'Field empty';
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
},
|
||||||
|
'email': (String? value) {
|
||||||
|
if (value == null || value.isEmpty) {
|
||||||
|
return 'Field empty';
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
inputDecorationField: {
|
||||||
|
'current_password': const InputDecoration(
|
||||||
constraints: BoxConstraints(
|
constraints: BoxConstraints(
|
||||||
maxHeight: 60,
|
maxHeight: 60,
|
||||||
maxWidth: 200,
|
maxWidth: 250,
|
||||||
),
|
),
|
||||||
),
|
hintText: 'Current password'),
|
||||||
'password_2': const InputDecoration(
|
'password_1': const InputDecoration(
|
||||||
constraints: BoxConstraints(
|
constraints: BoxConstraints(
|
||||||
maxHeight: 60,
|
maxHeight: 60,
|
||||||
maxWidth: 200,
|
maxWidth: 250,
|
||||||
),
|
),
|
||||||
),
|
hintText: 'New password'),
|
||||||
},
|
'password_2': const InputDecoration(
|
||||||
),
|
constraints: BoxConstraints(
|
||||||
user: _user,
|
maxHeight: 60,
|
||||||
service: ExampleProfileService(),
|
maxWidth: 250,
|
||||||
style: ProfileStyle(
|
),
|
||||||
avatarTextStyle: const TextStyle(fontSize: 20),
|
hintText: 'Repeat new password'),
|
||||||
pagePadding: EdgeInsets.only(
|
},
|
||||||
top: 50,
|
),
|
||||||
bottom: 50,
|
user: _user,
|
||||||
left: width * 0.1,
|
service: ExampleProfileService(),
|
||||||
right: width * 0.1,
|
style: ProfileStyle(
|
||||||
),
|
avatarTextStyle: const TextStyle(fontSize: 20),
|
||||||
|
pagePadding: EdgeInsets.only(
|
||||||
|
top: 50,
|
||||||
|
bottom: 50,
|
||||||
|
left: width * 0.1,
|
||||||
|
right: width * 0.1,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
|
@ -30,7 +30,10 @@ class ExampleProfileService extends ProfileService {
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
FutureOr<void> changePassword(String password) {
|
FutureOr<bool> changePassword(
|
||||||
debugPrint(password);
|
BuildContext context, String currentPassword, String newPassword) {
|
||||||
|
debugPrint('$currentPassword -> $newPassword');
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -122,11 +122,11 @@ packages:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
path: "."
|
path: "."
|
||||||
ref: "2.7.0"
|
ref: "3.1.0"
|
||||||
resolved-ref: "8eb1d80a9f08be0b7fe70078104d1a8851083edd"
|
resolved-ref: "5fca291c5e79c9ad6dad500e4ea5d9b628ee0f5d"
|
||||||
url: "https://github.com/Iconica-Development/flutter_input_library"
|
url: "https://github.com/Iconica-Development/flutter_input_library"
|
||||||
source: git
|
source: git
|
||||||
version: "2.7.0"
|
version: "3.1.0"
|
||||||
flutter_lints:
|
flutter_lints:
|
||||||
dependency: "direct dev"
|
dependency: "direct dev"
|
||||||
description:
|
description:
|
||||||
|
|
|
@ -47,10 +47,10 @@ class User {
|
||||||
|
|
||||||
/// ProfileData is used to store custom/addintional data for a user.
|
/// ProfileData is used to store custom/addintional data for a user.
|
||||||
///
|
///
|
||||||
/// The MapWidget method is used to bind a [Widget] to one of the keys.
|
/// The MapWidget method is used to bind a [Widget] to one of the keys.
|
||||||
/// This will override the standard textfield.
|
/// This will override the standard textfield.
|
||||||
///
|
///
|
||||||
/// The Builditems method is used to make the list of
|
/// The Builditems method is used to make the list of
|
||||||
/// field to house the user data.
|
/// field to house the user data.
|
||||||
abstract class ProfileData {
|
abstract class ProfileData {
|
||||||
const ProfileData();
|
const ProfileData();
|
||||||
|
|
|
@ -6,15 +6,18 @@ import 'dart:async';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_profile/src/models/user.dart';
|
import 'package:flutter_profile/src/models/user.dart';
|
||||||
|
|
||||||
/// ProfileService can be extended and set for the profilePage.
|
/// ProfileService can be extended and set for the profilePage.
|
||||||
/// The following method can be overriden.
|
/// The following method can be overriden.
|
||||||
///
|
///
|
||||||
/// BottompageAction is called when the [InkWell] at the bottom of
|
/// BottompageAction is called when the [InkWell] at the bottom of
|
||||||
/// the page is tapped.
|
/// the page is tapped.
|
||||||
///
|
///
|
||||||
/// EditProfile is called when a user changes and submits a standard textfields.
|
/// EditProfile is called when a user changes and submits a standard textfields.
|
||||||
///
|
///
|
||||||
/// UploadImage is called when te user presses the avatar.
|
/// UploadImage is called when te user presses the avatar.
|
||||||
|
///
|
||||||
|
/// changePassword is called when the user requests to change his password.
|
||||||
|
/// Return true to clear the inputfields.
|
||||||
abstract class ProfileService {
|
abstract class ProfileService {
|
||||||
const ProfileService();
|
const ProfileService();
|
||||||
|
|
||||||
|
@ -28,5 +31,9 @@ abstract class ProfileService {
|
||||||
required Function(bool isUploading) onUploadStateChanged,
|
required Function(bool isUploading) onUploadStateChanged,
|
||||||
});
|
});
|
||||||
|
|
||||||
FutureOr<void> changePassword(String password);
|
FutureOr<bool> changePassword(
|
||||||
|
BuildContext context,
|
||||||
|
String currentPassword,
|
||||||
|
String newPassword,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,7 @@ import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_input_library/flutter_input_library.dart';
|
import 'package:flutter_input_library/flutter_input_library.dart';
|
||||||
import 'package:flutter_profile/src/widgets/item_builder/item_builder_options.dart';
|
import 'package:flutter_profile/src/widgets/item_builder/item_builder_options.dart';
|
||||||
|
|
||||||
/// ItemBuilder is used to set the standard textfield for each undefined
|
/// ItemBuilder is used to set the standard textfield for each undefined
|
||||||
/// users data item.
|
/// users data item.
|
||||||
///
|
///
|
||||||
/// Options sets options for the textfield.
|
/// Options sets options for the textfield.
|
||||||
|
@ -54,6 +54,7 @@ class ItemBuilder {
|
||||||
|
|
||||||
Widget buildPassword(
|
Widget buildPassword(
|
||||||
String key,
|
String key,
|
||||||
|
TextEditingController controller,
|
||||||
Function(String?) onChanged,
|
Function(String?) onChanged,
|
||||||
String? Function(String?) validator,
|
String? Function(String?) validator,
|
||||||
) {
|
) {
|
||||||
|
@ -61,6 +62,7 @@ class ItemBuilder {
|
||||||
options.inputDecorationField?[key] ?? options.inputDecoration;
|
options.inputDecorationField?[key] ?? options.inputDecoration;
|
||||||
|
|
||||||
return FlutterFormInputPassword(
|
return FlutterFormInputPassword(
|
||||||
|
controller: controller,
|
||||||
style: options.inputTextStyle,
|
style: options.inputTextStyle,
|
||||||
decoration: inputDecoration,
|
decoration: inputDecoration,
|
||||||
onChanged: onChanged,
|
onChanged: onChanged,
|
||||||
|
|
|
@ -4,11 +4,11 @@
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
/// ItemBuilderOptions is a class to store all settings for a field in the
|
/// ItemBuilderOptions is a class to store all settings for a field in the
|
||||||
/// profile page.
|
/// profile page.
|
||||||
///
|
///
|
||||||
/// InputDecoration sets the decoration for all standard textfields.
|
/// InputDecoration sets the decoration for all standard textfields.
|
||||||
/// This is overridden if a field specific decoration is set by
|
/// This is overridden if a field specific decoration is set by
|
||||||
/// inputDecorationField.
|
/// inputDecorationField.
|
||||||
///
|
///
|
||||||
/// inputDecorationField sets the inputdecoration by key of the user data field.
|
/// inputDecorationField sets the inputdecoration by key of the user data field.
|
||||||
|
|
|
@ -32,6 +32,11 @@ class _ChangePasswordState extends State<ChangePassword> {
|
||||||
|
|
||||||
late final Widget? changePasswordChild;
|
late final Widget? changePasswordChild;
|
||||||
|
|
||||||
|
late var currentPasswordController = TextEditingController();
|
||||||
|
late var password1Controller = TextEditingController();
|
||||||
|
late var password2Controller = TextEditingController();
|
||||||
|
|
||||||
|
String? currentPassword;
|
||||||
String? password1;
|
String? password1;
|
||||||
String? password2;
|
String? password2;
|
||||||
|
|
||||||
|
@ -51,8 +56,21 @@ class _ChangePasswordState extends State<ChangePassword> {
|
||||||
runSpacing: widget.wrapViewOptions?.runSpacing ?? 0,
|
runSpacing: widget.wrapViewOptions?.runSpacing ?? 0,
|
||||||
clipBehavior: widget.wrapViewOptions?.clipBehavior ?? Clip.none,
|
clipBehavior: widget.wrapViewOptions?.clipBehavior ?? Clip.none,
|
||||||
children: [
|
children: [
|
||||||
|
builder.buildPassword(
|
||||||
|
'current_password',
|
||||||
|
currentPasswordController,
|
||||||
|
(value) => currentPassword = value,
|
||||||
|
(value) {
|
||||||
|
if (currentPassword?.isEmpty ?? true) {
|
||||||
|
return config.fieldRequiredErrorText;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
},
|
||||||
|
),
|
||||||
builder.buildPassword(
|
builder.buildPassword(
|
||||||
'password_1',
|
'password_1',
|
||||||
|
password1Controller,
|
||||||
(value) => password1 = value,
|
(value) => password1 = value,
|
||||||
(value) {
|
(value) {
|
||||||
if (password1?.isEmpty ?? true) {
|
if (password1?.isEmpty ?? true) {
|
||||||
|
@ -64,6 +82,7 @@ class _ChangePasswordState extends State<ChangePassword> {
|
||||||
),
|
),
|
||||||
builder.buildPassword(
|
builder.buildPassword(
|
||||||
'password_2',
|
'password_2',
|
||||||
|
password2Controller,
|
||||||
(value) => password2 = value,
|
(value) => password2 = value,
|
||||||
(value) {
|
(value) {
|
||||||
if (password2?.isEmpty ?? true) {
|
if (password2?.isEmpty ?? true) {
|
||||||
|
@ -90,14 +109,26 @@ class _ChangePasswordState extends State<ChangePassword> {
|
||||||
var theme = Theme.of(context);
|
var theme = Theme.of(context);
|
||||||
|
|
||||||
Future<void> onTapSave() async {
|
Future<void> onTapSave() async {
|
||||||
if ((_formKey.currentState?.validate() ?? false) && password2 != null) {
|
if ((_formKey.currentState?.validate() ?? false) &&
|
||||||
widget.service.changePassword(password2!);
|
currentPassword != null &&
|
||||||
|
password2 != null) {
|
||||||
|
if (await widget.service
|
||||||
|
.changePassword(context, currentPassword!, password2!)) {
|
||||||
|
currentPasswordController.clear();
|
||||||
|
password1Controller.clear();
|
||||||
|
password2Controller.clear();
|
||||||
|
|
||||||
|
currentPassword = null;
|
||||||
|
password1 = null;
|
||||||
|
password2 = null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return Form(
|
return Form(
|
||||||
key: _formKey,
|
key: _formKey,
|
||||||
child: Column(
|
child: Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
children: [
|
children: [
|
||||||
SizedBox(
|
SizedBox(
|
||||||
height: widget.style.betweenDefaultItemPadding * 2.5,
|
height: widget.style.betweenDefaultItemPadding * 2.5,
|
||||||
|
@ -127,7 +158,6 @@ class _ChangePasswordState extends State<ChangePassword> {
|
||||||
onPressed: onTapSave,
|
onPressed: onTapSave,
|
||||||
child: const Text('Save password'),
|
child: const Text('Save password'),
|
||||||
),
|
),
|
||||||
const Spacer(),
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
|
@ -4,12 +4,12 @@
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
/// ProfielStyle is used to set a couple of style paramaters for the
|
/// ProfielStyle is used to set a couple of style paramaters for the
|
||||||
/// whole profile page.
|
/// whole profile page.
|
||||||
///
|
///
|
||||||
/// AvatarStyle is used to set some styling for the avatar using [AvatarStyle].
|
/// AvatarStyle is used to set some styling for the avatar using [AvatarStyle].
|
||||||
///
|
///
|
||||||
/// PagePaddign is used to set the padding around the whole profile page
|
/// PagePaddign is used to set the padding around the whole profile page
|
||||||
/// with its parent.
|
/// with its parent.
|
||||||
///
|
///
|
||||||
/// BetweenDefaultitemPadding sets te padding between each user data item.
|
/// BetweenDefaultitemPadding sets te padding between each user data item.
|
||||||
|
@ -24,7 +24,7 @@ class ProfileStyle {
|
||||||
/// AvatarStyle can be used to set some avatar styling parameters.
|
/// AvatarStyle can be used to set some avatar styling parameters.
|
||||||
final TextStyle avatarTextStyle;
|
final TextStyle avatarTextStyle;
|
||||||
|
|
||||||
/// PagePadding can be set to determine the padding of the whole page
|
/// PagePadding can be set to determine the padding of the whole page
|
||||||
/// againt the profile page parent.
|
/// againt the profile page parent.
|
||||||
final EdgeInsetsGeometry pagePadding;
|
final EdgeInsetsGeometry pagePadding;
|
||||||
|
|
||||||
|
|
|
@ -74,9 +74,9 @@ class _ProfileWrapperState extends State<ProfileWrapper> {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
|
super.initState();
|
||||||
_formKey = widget.formKey ?? GlobalKey<FormState>();
|
_formKey = widget.formKey ?? GlobalKey<FormState>();
|
||||||
|
|
||||||
super.initState();
|
|
||||||
if (widget.showDefaultItems) {
|
if (widget.showDefaultItems) {
|
||||||
if (widget.itemBuilder == null) {
|
if (widget.itemBuilder == null) {
|
||||||
var builder = ItemBuilder(
|
var builder = ItemBuilder(
|
||||||
|
@ -196,50 +196,55 @@ class _ProfileWrapperState extends State<ProfileWrapper> {
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) => Material(
|
Widget build(BuildContext context) => Stack(
|
||||||
color: Colors.transparent,
|
children: [
|
||||||
child: SingleChildScrollView(
|
SizedBox(
|
||||||
child: SizedBox(
|
|
||||||
height: MediaQuery.of(context).size.height,
|
height: MediaQuery.of(context).size.height,
|
||||||
child: Padding(
|
width: MediaQuery.of(context).size.width,
|
||||||
padding: widget.style.pagePadding,
|
child: SingleChildScrollView(
|
||||||
child: Column(
|
child: Padding(
|
||||||
children: [
|
padding: widget.style.pagePadding,
|
||||||
if (widget.showAvatar) ...[
|
child: Column(
|
||||||
InkWell(
|
children: [
|
||||||
onTap: () async => widget.service.uploadImage(
|
if (widget.showAvatar) ...[
|
||||||
context,
|
InkWell(
|
||||||
onUploadStateChanged: (bool isUploading) => setState(
|
onTap: () async => widget.service.uploadImage(
|
||||||
() {
|
context,
|
||||||
_isUploadingImage = isUploading;
|
onUploadStateChanged: (isUploading) => setState(
|
||||||
},
|
() {
|
||||||
|
_isUploadingImage = isUploading;
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
child: AvatarWrapper(
|
||||||
|
avatarBackgroundColor: widget.avatarBackgroundColor,
|
||||||
|
user: widget.user,
|
||||||
|
textStyle: widget.style.avatarTextStyle,
|
||||||
|
customAvatar: _isUploadingImage
|
||||||
|
? Container(
|
||||||
|
width: 100,
|
||||||
|
height: 100,
|
||||||
|
decoration: const BoxDecoration(
|
||||||
|
color: Colors.black,
|
||||||
|
shape: BoxShape.circle,
|
||||||
|
),
|
||||||
|
child: const CircularProgressIndicator(),
|
||||||
|
)
|
||||||
|
: widget.customAvatar,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
child: AvatarWrapper(
|
SizedBox(
|
||||||
avatarBackgroundColor: widget.avatarBackgroundColor,
|
height: widget.style.betweenDefaultItemPadding,
|
||||||
user: widget.user,
|
|
||||||
textStyle: widget.style.avatarTextStyle,
|
|
||||||
customAvatar: _isUploadingImage
|
|
||||||
? Container(
|
|
||||||
width: 100,
|
|
||||||
height: 100,
|
|
||||||
decoration: const BoxDecoration(
|
|
||||||
color: Colors.black,
|
|
||||||
shape: BoxShape.circle,
|
|
||||||
),
|
|
||||||
child: const CircularProgressIndicator(),
|
|
||||||
)
|
|
||||||
: widget.customAvatar,
|
|
||||||
),
|
),
|
||||||
),
|
],
|
||||||
SizedBox(
|
if (widget.showItems) ...[
|
||||||
height: widget.style.betweenDefaultItemPadding,
|
Form(
|
||||||
),
|
key: _formKey,
|
||||||
],
|
child: child,
|
||||||
if (widget.showItems) Form(key: _formKey, child: child),
|
),
|
||||||
if (widget.changePasswordConfig.enablePasswordChange) ...[
|
],
|
||||||
Expanded(
|
if (widget.changePasswordConfig.enablePasswordChange) ...[
|
||||||
child: ChangePassword(
|
ChangePassword(
|
||||||
config: widget.changePasswordConfig,
|
config: widget.changePasswordConfig,
|
||||||
service: widget.service,
|
service: widget.service,
|
||||||
wrapViewOptions: widget.wrapViewOptions,
|
wrapViewOptions: widget.wrapViewOptions,
|
||||||
|
@ -248,42 +253,35 @@ class _ProfileWrapperState extends State<ProfileWrapper> {
|
||||||
itemBuilderOptions: widget.itemBuilderOptions,
|
itemBuilderOptions: widget.itemBuilderOptions,
|
||||||
style: widget.style,
|
style: widget.style,
|
||||||
),
|
),
|
||||||
),
|
|
||||||
],
|
|
||||||
if (widget.bottomActionText != null) ...[
|
|
||||||
SizedBox(
|
|
||||||
height: widget.style.betweenDefaultItemPadding,
|
|
||||||
),
|
|
||||||
if (!widget.changePasswordConfig.enablePasswordChange) ...[
|
|
||||||
const Spacer(),
|
|
||||||
],
|
],
|
||||||
InkWell(
|
|
||||||
onTap: () async {
|
|
||||||
widget.service.pageBottomAction();
|
|
||||||
},
|
|
||||||
child: Padding(
|
|
||||||
padding: const EdgeInsets.all(8.0),
|
|
||||||
child: Text(
|
|
||||||
widget.bottomActionText!,
|
|
||||||
style: widget.style.bottomActionTextStyle,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
],
|
||||||
if (widget.bottomActionText == null &&
|
),
|
||||||
!widget.changePasswordConfig.enablePasswordChange) ...[
|
|
||||||
const Spacer(),
|
|
||||||
],
|
|
||||||
],
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
if (widget.bottomActionText != null &&
|
||||||
|
MediaQuery.of(Scaffold.of(context).context).viewInsets.bottom ==
|
||||||
|
0.0) ...[
|
||||||
|
Align(
|
||||||
|
alignment: Alignment.bottomCenter,
|
||||||
|
child: InkWell(
|
||||||
|
onTap: () async => await widget.service.pageBottomAction(),
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.all(8.0),
|
||||||
|
child: Text(
|
||||||
|
widget.bottomActionText!,
|
||||||
|
style: widget.style.bottomActionTextStyle,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
],
|
||||||
);
|
);
|
||||||
|
|
||||||
/// This calls onSaved on all the fiels which check if they have a new value
|
/// This calls onSaved on all the fiels which check if they have a new value
|
||||||
void submitAllChangedFields() {
|
void submitAllChangedFields() {
|
||||||
if (_formKey.currentState!.validate()) {
|
if (_formKey.currentState?.validate() ?? false) {
|
||||||
_formKey.currentState!.save();
|
_formKey.currentState!.save();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
name: flutter_profile
|
name: flutter_profile
|
||||||
description: Flutter profile package
|
description: Flutter profile package
|
||||||
version: 1.2.1
|
version: 1.3.0
|
||||||
repository: https://github.com/Iconica-Development/flutter_profile
|
repository: https://github.com/Iconica-Development/flutter_profile
|
||||||
|
|
||||||
publish_to: none
|
publish_to: none
|
||||||
|
@ -15,7 +15,7 @@ dependencies:
|
||||||
flutter_input_library:
|
flutter_input_library:
|
||||||
git:
|
git:
|
||||||
url: https://github.com/Iconica-Development/flutter_input_library
|
url: https://github.com/Iconica-Development/flutter_input_library
|
||||||
ref: 2.7.0
|
ref: 3.1.0
|
||||||
|
|
||||||
flutter:
|
flutter:
|
||||||
sdk: flutter
|
sdk: flutter
|
||||||
|
|
|
@ -28,5 +28,10 @@ class TestProfileService extends ProfileService {
|
||||||
}) {}
|
}) {}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
FutureOr<void> changePassword(String password) {}
|
FutureOr<bool> changePassword(
|
||||||
|
BuildContext context,
|
||||||
|
String currentPassword,
|
||||||
|
String newPassword,
|
||||||
|
) =>
|
||||||
|
true;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue