mirror of
https://github.com/Iconica-Development/flutter_profile.git
synced 2025-05-19 01:03:45 +02:00
Merge branch 'feature/add_ci_linter'
This commit is contained in:
commit
c523678e74
20 changed files with 259 additions and 203 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
|
|
@ -1,3 +1,7 @@
|
|||
## 1.2.1
|
||||
|
||||
- Added Iconica CI and Iconica Linter
|
||||
|
||||
## 1.2.0
|
||||
|
||||
- Added the posibilty to enable the user to change it's password.
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -141,7 +141,7 @@ packages:
|
|||
path: ".."
|
||||
relative: true
|
||||
source: path
|
||||
version: "1.1.6"
|
||||
version: "1.2.0"
|
||||
flutter_test:
|
||||
dependency: "direct dev"
|
||||
description: flutter
|
||||
|
|
|
@ -1,15 +1,15 @@
|
|||
// SPDX-FileCopyrightText: 2022 Iconica
|
||||
//
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
///
|
||||
library flutter_profile;
|
||||
|
||||
export 'src/models/change_password_config.dart';
|
||||
export 'src/models/user.dart';
|
||||
export 'src/services/profile_service.dart';
|
||||
export 'src/widgets/avatar/avatar.dart';
|
||||
export 'src/widgets/avatar/avatar_wrapper.dart';
|
||||
export 'src/widgets/item_builder/item_builder.dart';
|
||||
export 'src/widgets/item_builder/item_builder_options.dart';
|
||||
export 'src/widgets/profile/profile_page.dart';
|
||||
export 'src/widgets/profile/profile_style.dart';
|
||||
export 'src/widgets/avatar/avatar_wrapper.dart';
|
||||
export 'src/widgets/avatar/avatar.dart';
|
||||
export 'src/services/profile_service.dart';
|
||||
export 'src/widgets/item_builder/item_builder.dart';
|
||||
export 'src/models/user.dart';
|
||||
export 'src/models/change_password_config.dart';
|
||||
export 'src/widgets/item_builder/item_builder_options.dart';
|
||||
|
|
|
@ -39,6 +39,7 @@ class ChangePasswordConfig {
|
|||
/// Error text to be shown when either of the textfields is empty.
|
||||
final String fieldRequiredErrorText;
|
||||
|
||||
/// Error text to be shown when the second password isn't equal to the first password.
|
||||
/// Error text to be shown when the second password isn't equal
|
||||
/// to the first password.
|
||||
final String notEqualErrorText;
|
||||
}
|
||||
|
|
|
@ -10,12 +10,6 @@ import 'package:flutter/material.dart';
|
|||
///
|
||||
/// For additional data profileData can be used.
|
||||
class User {
|
||||
String? firstName;
|
||||
String? lastName;
|
||||
Uint8List? image;
|
||||
String? imageUrl;
|
||||
ProfileData? profileData;
|
||||
|
||||
User({
|
||||
this.firstName,
|
||||
this.lastName,
|
||||
|
@ -24,10 +18,6 @@ class User {
|
|||
this.profileData,
|
||||
});
|
||||
|
||||
String get displayName => '${firstName ?? ''} ${lastName ?? ''}';
|
||||
String get initials =>
|
||||
'${(firstName?.isNotEmpty ?? false) ? firstName![0] : ''}${(lastName?.isNotEmpty ?? false) ? lastName![0] : ''}';
|
||||
|
||||
factory User.fromMap(Map<String, dynamic> data) => User(
|
||||
firstName: data['first_name'],
|
||||
lastName: data['last_name'],
|
||||
|
@ -35,6 +25,16 @@ class User {
|
|||
imageUrl: data['image_url'],
|
||||
profileData: data['profile_data'],
|
||||
);
|
||||
String? firstName;
|
||||
String? lastName;
|
||||
Uint8List? image;
|
||||
String? imageUrl;
|
||||
ProfileData? profileData;
|
||||
|
||||
String get displayName => '${firstName ?? ''} ${lastName ?? ''}';
|
||||
String get initials =>
|
||||
'${(firstName?.isNotEmpty ?? false) ? firstName![0] : ''}'
|
||||
'${(lastName?.isNotEmpty ?? false) ? lastName![0] : ''}';
|
||||
|
||||
Map<String, dynamic> toMap() => {
|
||||
'first_name': firstName,
|
||||
|
@ -47,9 +47,11 @@ class 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. This will override the standard textfield.
|
||||
/// The MapWidget method is used to bind a [Widget] to one of the keys.
|
||||
/// This will override the standard textfield.
|
||||
///
|
||||
/// The Builditems method is used to make the list of field to house the user data.
|
||||
/// The Builditems method is used to make the list of
|
||||
/// field to house the user data.
|
||||
abstract class ProfileData {
|
||||
const ProfileData();
|
||||
|
||||
|
|
|
@ -6,9 +6,11 @@ import 'dart:async';
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_profile/src/models/user.dart';
|
||||
|
||||
/// ProfileService can be extended and set for the profilePage. The following method can be overriden.
|
||||
/// ProfileService can be extended and set for the profilePage.
|
||||
/// The following method can be overriden.
|
||||
///
|
||||
/// BottompageAction is called when the [InkWell] at the bottom of the page is tapped.
|
||||
/// BottompageAction is called when the [InkWell] at the bottom of
|
||||
/// the page is tapped.
|
||||
///
|
||||
/// EditProfile is called when a user changes and submits a standard textfields.
|
||||
///
|
||||
|
@ -22,6 +24,7 @@ abstract class ProfileService {
|
|||
|
||||
FutureOr<void> uploadImage(
|
||||
BuildContext context, {
|
||||
// ignore: avoid_positional_boolean_parameters
|
||||
required Function(bool isUploading) onUploadStateChanged,
|
||||
});
|
||||
|
||||
|
|
|
@ -8,11 +8,11 @@ import 'package:flutter_profile/src/models/user.dart';
|
|||
|
||||
class Avatar extends StatelessWidget {
|
||||
const Avatar({
|
||||
Key? key,
|
||||
super.key,
|
||||
this.user,
|
||||
this.size = 100,
|
||||
this.avatarBackgroundColor,
|
||||
}) : super(key: key);
|
||||
});
|
||||
|
||||
final User? user;
|
||||
final double size;
|
||||
|
|
|
@ -8,15 +8,15 @@ import 'package:flutter_profile/src/widgets/avatar/avatar.dart';
|
|||
|
||||
class AvatarWrapper extends StatelessWidget {
|
||||
const AvatarWrapper({
|
||||
Key? key,
|
||||
required this.user,
|
||||
super.key,
|
||||
this.showName = false,
|
||||
this.padding = const EdgeInsets.only(top: 16),
|
||||
this.size = 100,
|
||||
this.textStyle,
|
||||
this.customAvatar,
|
||||
this.avatarBackgroundColor,
|
||||
}) : super(key: key);
|
||||
});
|
||||
|
||||
final User user;
|
||||
final Widget? customAvatar;
|
||||
|
|
|
@ -6,7 +6,8 @@ import 'package:flutter/material.dart';
|
|||
import 'package:flutter_input_library/flutter_input_library.dart';
|
||||
import 'package:flutter_profile/src/widgets/item_builder/item_builder_options.dart';
|
||||
|
||||
/// ItemBuilder is used to set the standard textfield for each undefined users data item.
|
||||
/// ItemBuilder is used to set the standard textfield for each undefined
|
||||
/// users data item.
|
||||
///
|
||||
/// Options sets options for the textfield.
|
||||
class ItemBuilder {
|
||||
|
@ -16,8 +17,13 @@ class ItemBuilder {
|
|||
|
||||
final ItemBuilderOptions options;
|
||||
|
||||
Widget build(String key, dynamic value, Widget? widget,
|
||||
Function(String) updateItem, Function(String?) saveItem) {
|
||||
Widget build(
|
||||
String key,
|
||||
value,
|
||||
Widget? widget,
|
||||
Function(String) updateItem,
|
||||
Function(String?) saveItem,
|
||||
) {
|
||||
if (widget == null) {
|
||||
var controller = TextEditingController(
|
||||
text: '${value ?? ''}',
|
||||
|
@ -40,9 +46,7 @@ class ItemBuilder {
|
|||
onSaved: (newValue) {
|
||||
saveItem(newValue);
|
||||
},
|
||||
validator: (value) {
|
||||
return options.validators?[key]?.call(value);
|
||||
},
|
||||
validator: (value) => options.validators?[key]?.call(value),
|
||||
);
|
||||
}
|
||||
return widget;
|
||||
|
|
|
@ -4,17 +4,22 @@
|
|||
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
/// ItemBuilderOptions is a class to store all settings for a field in the profile page.
|
||||
/// ItemBuilderOptions is a class to store all settings for a field in the
|
||||
/// profile page.
|
||||
///
|
||||
/// InputDecoration sets the decoration for all standard textfields. This is overridden if a field specific decoration is set by inputDecorationField.
|
||||
/// InputDecoration sets the decoration for all standard textfields.
|
||||
/// This is overridden if a field specific decoration is set by
|
||||
/// inputDecorationField.
|
||||
///
|
||||
/// inputDecorationField sets the inputdecoration by key of the user data field. So a field can have its own specific decoration.
|
||||
/// inputDecorationField sets the inputdecoration by key of the user data field.
|
||||
/// So a field can have its own specific decoration.
|
||||
///
|
||||
/// Validator can be used to set a validator for the standard textfield.
|
||||
class ItemBuilderOptions {
|
||||
ItemBuilderOptions({
|
||||
this.inputDecoration = const InputDecoration(
|
||||
constraints: BoxConstraints(maxWidth: 200, maxHeight: 40)),
|
||||
constraints: BoxConstraints(maxWidth: 200, maxHeight: 40),
|
||||
),
|
||||
this.inputDecorationField,
|
||||
this.readOnly = false,
|
||||
this.validators,
|
||||
|
|
|
@ -40,7 +40,7 @@ class ItemList {
|
|||
(value) {
|
||||
updateProfile(item.key, value);
|
||||
},
|
||||
)
|
||||
),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -89,7 +89,7 @@ class _ChangePasswordState extends State<ChangePassword> {
|
|||
Widget build(BuildContext context) {
|
||||
var theme = Theme.of(context);
|
||||
|
||||
void onTapSave() {
|
||||
Future<void> onTapSave() async {
|
||||
if ((_formKey.currentState?.validate() ?? false) && password2 != null) {
|
||||
widget.service.changePassword(password2!);
|
||||
}
|
||||
|
@ -121,10 +121,10 @@ class _ChangePasswordState extends State<ChangePassword> {
|
|||
),
|
||||
config.saveButtonBuilder?.call(
|
||||
context,
|
||||
() => onTapSave(),
|
||||
onTapSave,
|
||||
) ??
|
||||
FilledButton(
|
||||
onPressed: () => onTapSave(),
|
||||
onPressed: onTapSave,
|
||||
child: const Text('Save password'),
|
||||
),
|
||||
const Spacer(),
|
||||
|
|
|
@ -11,28 +11,37 @@ import 'package:flutter_profile/src/widgets/item_builder/item_builder_options.da
|
|||
import 'package:flutter_profile/src/widgets/profile/profile_style.dart';
|
||||
import 'package:flutter_profile/src/widgets/profile/profile_wrapper.dart';
|
||||
|
||||
/// The ProfilePage widget is able to show the data of a user. By default the user is able to change this data. The widget has a couple of parameters listed below:
|
||||
/// The ProfilePage widget is able to show the data of a user. By default the
|
||||
/// user is able to change this data. The widget has a couple of
|
||||
/// parameters listed below:
|
||||
///
|
||||
/// User will contain the data of the user which atleast contain a first name, last name and an avatar/image. Besides this information the [ProfileData] can be used to set custom user fields.
|
||||
///
|
||||
/// With the use of the service set by a [ProfileService] some actions can be determined what should occur when the user does the following actions: Deleting/editing the profile or uploading an image.
|
||||
///
|
||||
/// The style can be used the set some style options regarding the whole form. This is done by setting a [ProfileStyle]. The following styling can be set: The style of the avatar, the padding of the page and default padding between items.
|
||||
/// The style can be used the set some style options regarding the whole form.
|
||||
/// This is done by setting a [ProfileStyle]. The following styling can be set:
|
||||
/// The style of the avatar, the padding of the page and default
|
||||
/// padding between items.
|
||||
///
|
||||
/// CustomAvatar can be set to override the standard avatar using any [Widget].
|
||||
///
|
||||
/// ShowAvatar can be set using a [bool] to determine whether the avatar should be shown and be able to be set by the user. Default set to true.
|
||||
/// ShowAvatar can be set using a [bool] to determine whether the avatar should
|
||||
/// be shown and be able to be set by the user. Default set to true.
|
||||
///
|
||||
/// BottomActionText sets the text for the inkwell at the bottom of the page. If this is set the null then the [InkWell] is disabled.
|
||||
/// BottomActionText sets the text for the inkwell at the bottom of the page.
|
||||
/// If this is set the null then the [InkWell] is disabled.
|
||||
///
|
||||
/// ItemBuilder is used to determine how the user data is represented.
|
||||
///
|
||||
/// ItemBuilderOptions can be used to just set the settings for fields instead of defining the field itself and how it is used. This field should not be used when the itemBuilder is set.
|
||||
/// ItemBuilderOptions can be used to just set the settings for fields instead
|
||||
/// of defining the field itself and how it is used. This field should not
|
||||
/// be used when the itemBuilder is set.
|
||||
class ProfilePage extends StatefulWidget {
|
||||
const ProfilePage({
|
||||
Key? key,
|
||||
required this.user,
|
||||
required this.service,
|
||||
super.key,
|
||||
this.style = const ProfileStyle(),
|
||||
this.customAvatar,
|
||||
this.showAvatar = true,
|
||||
|
@ -49,7 +58,7 @@ class ProfilePage extends StatefulWidget {
|
|||
this.formKey,
|
||||
this.changePasswordConfig =
|
||||
const ChangePasswordConfig(enablePasswordChange: false),
|
||||
}) : super(key: key);
|
||||
});
|
||||
|
||||
/// User containing all the user data.
|
||||
final User user;
|
||||
|
@ -69,10 +78,12 @@ class ProfilePage extends StatefulWidget {
|
|||
///The background color of the avatar when no image is available.
|
||||
final Color? avatarBackgroundColor;
|
||||
|
||||
/// Whether you want to show the input fields, sometimes you just want to edit the avatar.
|
||||
/// Whether you want to show the input fields, sometimes you just want
|
||||
/// to edit the avatar.
|
||||
final bool showItems;
|
||||
|
||||
/// Sets the text for the [InkWell] at the bottom of the profile page. The [InkWell] is disabled when null.
|
||||
/// Sets the text for the [InkWell] at the bottom of the profile page.
|
||||
/// The [InkWell] is disabled when null.
|
||||
final String? bottomActionText;
|
||||
|
||||
/// Itembuilder is used the build each field in the user.
|
||||
|
@ -84,7 +95,8 @@ class ProfilePage extends StatefulWidget {
|
|||
/// Customize the parent widget for all fields
|
||||
final Widget Function(BuildContext context, Widget child)? wrapItemsBuilder;
|
||||
|
||||
/// Map keys of items that should be shown first before the default items and the rest of the items.
|
||||
/// Map keys of items that should be shown first before the default
|
||||
/// items and the rest of the items.
|
||||
final List<String> prioritizedItems;
|
||||
|
||||
/// Shows textfields for firstname and lastname if is set to true
|
||||
|
@ -93,7 +105,8 @@ class ProfilePage extends StatefulWidget {
|
|||
/// Edit the direction and spacing between every item
|
||||
final WrapViewOptions? wrapViewOptions;
|
||||
|
||||
/// The map of extra widgets that might want to be added like empty SizedBoxes for styling.
|
||||
/// The map of extra widgets that might want to be added like empty
|
||||
/// SizedBoxes for styling.
|
||||
final Map<String, Widget>? extraWidgets;
|
||||
|
||||
/// Use the form key to save on any custom callback
|
||||
|
@ -108,8 +121,7 @@ class ProfilePage extends StatefulWidget {
|
|||
|
||||
class _ProfilePageState extends State<ProfilePage> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return ProfileWrapper(
|
||||
Widget build(BuildContext context) => ProfileWrapper(
|
||||
service: widget.service,
|
||||
user: widget.user,
|
||||
rebuild: () {
|
||||
|
@ -132,15 +144,15 @@ class _ProfilePageState extends State<ProfilePage> {
|
|||
changePasswordConfig: widget.changePasswordConfig,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class WrapViewOptions {
|
||||
WrapViewOptions(
|
||||
{this.direction,
|
||||
WrapViewOptions({
|
||||
this.direction,
|
||||
this.spacing,
|
||||
this.wrapAlignment,
|
||||
this.runSpacing,
|
||||
this.clipBehavior});
|
||||
this.clipBehavior,
|
||||
});
|
||||
Axis? direction;
|
||||
double? spacing;
|
||||
double? runSpacing;
|
||||
|
|
|
@ -4,11 +4,13 @@
|
|||
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
/// ProfielStyle is used to set a couple of style paramaters for the whole profile page.
|
||||
/// ProfielStyle is used to set a couple of style paramaters for the
|
||||
/// whole profile page.
|
||||
///
|
||||
/// AvatarStyle is used to set some styling for the avatar using [AvatarStyle].
|
||||
///
|
||||
/// PagePaddign is used to set the padding around the whole profile page with its parent.
|
||||
/// PagePaddign is used to set the padding around the whole profile page
|
||||
/// with its parent.
|
||||
///
|
||||
/// BetweenDefaultitemPadding sets te padding between each user data item.
|
||||
class ProfileStyle {
|
||||
|
@ -22,7 +24,8 @@ class ProfileStyle {
|
|||
/// AvatarStyle can be used to set some avatar styling parameters.
|
||||
final TextStyle avatarTextStyle;
|
||||
|
||||
/// PagePadding can be set to determine the padding of the whole page againt the profile page parent.
|
||||
/// PagePadding can be set to determine the padding of the whole page
|
||||
/// againt the profile page parent.
|
||||
final EdgeInsetsGeometry pagePadding;
|
||||
|
||||
/// BetweenDefaultItemPadding sets the
|
||||
|
|
|
@ -47,7 +47,7 @@ class ProfileWrapper extends StatefulWidget {
|
|||
final String? bottomActionText;
|
||||
final ItemBuilder? itemBuilder;
|
||||
final WrapViewOptions? wrapViewOptions;
|
||||
final Function rebuild;
|
||||
final Function() rebuild;
|
||||
final ItemBuilderOptions? itemBuilderOptions;
|
||||
final bool showDefaultItems;
|
||||
final bool showItems;
|
||||
|
@ -56,7 +56,8 @@ class ProfileWrapper extends StatefulWidget {
|
|||
final GlobalKey<FormState>? formKey;
|
||||
final ChangePasswordConfig changePasswordConfig;
|
||||
|
||||
/// Map keys of items that should be shown first before the default items and the rest of the items.
|
||||
/// Map keys of items that should be shown first before the default items and
|
||||
/// the rest of the items.
|
||||
final List<String> prioritizedItems;
|
||||
|
||||
@override
|
||||
|
@ -78,7 +79,7 @@ class _ProfileWrapperState extends State<ProfileWrapper> {
|
|||
super.initState();
|
||||
if (widget.showDefaultItems) {
|
||||
if (widget.itemBuilder == null) {
|
||||
ItemBuilder builder = ItemBuilder(
|
||||
var builder = ItemBuilder(
|
||||
options: widget.itemBuilderOptions ?? ItemBuilderOptions(),
|
||||
);
|
||||
defaultItems.addAll({
|
||||
|
@ -89,7 +90,7 @@ class _ProfileWrapperState extends State<ProfileWrapper> {
|
|||
(value) {
|
||||
submitAllChangedFields();
|
||||
},
|
||||
(v) {
|
||||
(v) async {
|
||||
if (widget.user.firstName != v) {
|
||||
widget.user.firstName = v;
|
||||
widget.service.editProfile(widget.user, 'first_name', v);
|
||||
|
@ -103,7 +104,7 @@ class _ProfileWrapperState extends State<ProfileWrapper> {
|
|||
(value) {
|
||||
submitAllChangedFields();
|
||||
},
|
||||
(v) {
|
||||
(v) async {
|
||||
if (widget.user.lastName != v) {
|
||||
widget.user.lastName = v;
|
||||
widget.service.editProfile(widget.user, 'last_name', v);
|
||||
|
@ -120,7 +121,7 @@ class _ProfileWrapperState extends State<ProfileWrapper> {
|
|||
(value) {
|
||||
submitAllChangedFields();
|
||||
},
|
||||
(v) {
|
||||
(v) async {
|
||||
if (widget.user.firstName != v) {
|
||||
widget.user.firstName = v;
|
||||
widget.service.editProfile(widget.user, 'first_name', v);
|
||||
|
@ -134,7 +135,7 @@ class _ProfileWrapperState extends State<ProfileWrapper> {
|
|||
(value) {
|
||||
submitAllChangedFields();
|
||||
},
|
||||
(v) {
|
||||
(v) async {
|
||||
if (widget.user.lastName != v) {
|
||||
widget.user.lastName = v;
|
||||
widget.service.editProfile(widget.user, 'last_name', v);
|
||||
|
@ -147,7 +148,8 @@ class _ProfileWrapperState extends State<ProfileWrapper> {
|
|||
widgets.addAll(widget.extraWidgets ?? {});
|
||||
widgets.addAll(defaultItems);
|
||||
if (widget.user.profileData != null) {
|
||||
widgets.addAll(ItemList(
|
||||
widgets.addAll(
|
||||
ItemList(
|
||||
Map.fromEntries(widget.user.profileData!.toMap().entries),
|
||||
widget.user.profileData!.mapWidget(
|
||||
() {
|
||||
|
@ -155,20 +157,19 @@ class _ProfileWrapperState extends State<ProfileWrapper> {
|
|||
},
|
||||
context,
|
||||
),
|
||||
(key, value) {
|
||||
if (widget.user.toMap()['profile_data'][key] == null) {
|
||||
(key, value) async {
|
||||
if (widget.user.profileData?.toMap()[key] == null) {
|
||||
widget.service.editProfile(widget.user, key, value);
|
||||
} else if (widget.user.toMap()['profile_data'][key] != value) {
|
||||
} else if (widget.user.profileData?.toMap()[key] != value) {
|
||||
widget.service.editProfile(widget.user, key, value);
|
||||
}
|
||||
},
|
||||
() {
|
||||
submitAllChangedFields();
|
||||
},
|
||||
submitAllChangedFields,
|
||||
itemBuilder: widget.itemBuilder,
|
||||
itemBuilderOptions: widget.itemBuilderOptions,
|
||||
formKey: _formKey,
|
||||
).getItemList());
|
||||
).getItemList(),
|
||||
);
|
||||
}
|
||||
|
||||
var items = Wrap(
|
||||
|
@ -195,8 +196,7 @@ class _ProfileWrapperState extends State<ProfileWrapper> {
|
|||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Material(
|
||||
Widget build(BuildContext context) => Material(
|
||||
color: Colors.transparent,
|
||||
child: SingleChildScrollView(
|
||||
child: SizedBox(
|
||||
|
@ -207,9 +207,9 @@ class _ProfileWrapperState extends State<ProfileWrapper> {
|
|||
children: [
|
||||
if (widget.showAvatar) ...[
|
||||
InkWell(
|
||||
onTap: () => widget.service.uploadImage(
|
||||
onTap: () async => widget.service.uploadImage(
|
||||
context,
|
||||
onUploadStateChanged: (isUploading) => setState(
|
||||
onUploadStateChanged: (bool isUploading) => setState(
|
||||
() {
|
||||
_isUploadingImage = isUploading;
|
||||
},
|
||||
|
@ -258,7 +258,7 @@ class _ProfileWrapperState extends State<ProfileWrapper> {
|
|||
const Spacer(),
|
||||
],
|
||||
InkWell(
|
||||
onTap: () {
|
||||
onTap: () async {
|
||||
widget.service.pageBottomAction();
|
||||
},
|
||||
child: Padding(
|
||||
|
@ -273,14 +273,13 @@ class _ProfileWrapperState extends State<ProfileWrapper> {
|
|||
if (widget.bottomActionText == null &&
|
||||
!widget.changePasswordConfig.enablePasswordChange) ...[
|
||||
const Spacer(),
|
||||
]
|
||||
],
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/// This calls onSaved on all the fiels which check if they have a new value
|
||||
void submitAllChangedFields() {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
name: flutter_profile
|
||||
description: Flutter profile package
|
||||
version: 1.2.0
|
||||
version: 1.2.1
|
||||
repository: https://github.com/Iconica-Development/flutter_profile
|
||||
|
||||
publish_to: none
|
||||
|
@ -23,6 +23,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:
|
||||
|
|
|
@ -25,9 +25,9 @@ void main() {
|
|||
),
|
||||
);
|
||||
|
||||
final firstNameFinder = find.text('Firstname');
|
||||
final lastNameFinder = find.text('Lastname');
|
||||
final emailFinder = find.text('test@email.com');
|
||||
var firstNameFinder = find.text('Firstname');
|
||||
var lastNameFinder = find.text('Lastname');
|
||||
var emailFinder = find.text('test@email.com');
|
||||
|
||||
expect(firstNameFinder, findsOneWidget);
|
||||
expect(lastNameFinder, findsOneWidget);
|
||||
|
@ -74,13 +74,13 @@ void main() {
|
|||
await tester.testTextInput.receiveAction(TextInputAction.send);
|
||||
await tester.pump();
|
||||
|
||||
final firstNameFinder = find.text('Firstname');
|
||||
final firstNameEditedFinder = find.text('FirstEditedName');
|
||||
var firstNameFinder = find.text('Firstname');
|
||||
var firstNameEditedFinder = find.text('FirstEditedName');
|
||||
|
||||
final lastNameFinder = find.text('Lastname');
|
||||
var lastNameFinder = find.text('Lastname');
|
||||
|
||||
final emailFinder = find.text('test@email.com');
|
||||
final emailEditedFinder = find.text('edited@emial.com');
|
||||
var emailFinder = find.text('test@email.com');
|
||||
var emailEditedFinder = find.text('edited@emial.com');
|
||||
|
||||
expect(firstNameFinder, findsNothing);
|
||||
expect(firstNameEditedFinder, findsOneWidget);
|
||||
|
|
|
@ -23,6 +23,7 @@ class TestProfileService extends ProfileService {
|
|||
@override
|
||||
FutureOr<void> uploadImage(
|
||||
BuildContext context, {
|
||||
// ignore: avoid_positional_boolean_parameters
|
||||
required Function(bool isUploading) onUploadStateChanged,
|
||||
}) {}
|
||||
|
||||
|
|
Loading…
Reference in a new issue