From 5b2757e19baf4732b7637b22b3480d98e4450e3d Mon Sep 17 00:00:00 2001 From: Joons van Stuijvenberg Date: Fri, 2 Dec 2022 10:40:16 +0100 Subject: [PATCH] removed column --- CHANGELOG.md | 6 +- example/lib/main.dart | 103 ++++---- example/lib/utils/example_profile_data.dart | 12 +- example/pubspec.lock | 2 +- lib/src/widgets/item_builder/item_list.dart | 92 +++---- lib/src/widgets/profile/profile_page.dart | 22 +- lib/src/widgets/profile/profile_wrapper.dart | 262 +++++++++---------- pubspec.yaml | 2 +- 8 files changed, 243 insertions(+), 258 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 035da9d..107d9eb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -24,4 +24,8 @@ ## 1.0.1 -* Added a default wrap instead of column \ No newline at end of file +* Added a default wrap instead of column + +## 1.0.2 + +* Added form key and more customizability for web \ No newline at end of file diff --git a/example/lib/main.dart b/example/lib/main.dart index f070c17..ba7f996 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -35,8 +35,8 @@ class ProfileExample extends StatefulWidget { class _ProfileExampleState extends State { late User _user; - ProfileData profileData = - ExampleProfileData().fromMap({'email': 'example@email.com'}); + ProfileData profileData = ExampleProfileData().fromMap( + {'email': 'example@email.com', 'about': 'about', 'remarks': 'remarks'}); @override void initState() { @@ -53,55 +53,62 @@ class _ProfileExampleState extends State { @override Widget build(BuildContext context) { + //get width and height + var width = MediaQuery.of(context).size.width; + return Scaffold( body: Center( - child: ProfilePage( - wrapViewOptions: - WrapViewOptions(direction: Axis.vertical, spacing: 16), - bottomActionText: 'Log out', - itemBuilderOptions: ItemBuilderOptions( - inputDecorationField: { - 'first_name': const InputDecoration( - constraints: BoxConstraints(maxHeight: 70, maxWidth: 200), - label: Text('First name'), + child: Column( + children: [ + SizedBox( + height: 400, + width: 800, + child: ProfilePage( + showItems: false, + prioritizedItems: const ['remarks', 'about'], + wrapViewOptions: WrapViewOptions( + direction: Axis.horizontal, + spacing: 16, + ), + bottomActionText: 'Log out', + itemBuilderOptions: ItemBuilderOptions( + //no label for email + validators: { + 'first_name': (String? value) { + if (value == null || value.isEmpty) { + return 'Field empty'; + } + 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; + }, + }, + ), + user: _user, + service: ExampleProfileService(), + style: ProfileStyle( + avatarTextStyle: const TextStyle(fontSize: 20), + pagePadding: EdgeInsets.only( + top: 50, + bottom: 50, + left: width * 0.1, + right: width * 0.1, + ), + ), ), - 'last_name': const InputDecoration( - constraints: BoxConstraints(maxHeight: 70, maxWidth: 150), - label: Text('First name'), - ), - }, - validators: { - 'first_name': (String? value) { - if (value == null || value.isEmpty) { - return 'Field empty'; - } - 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; - }, - }, - ), - user: _user, - service: ExampleProfileService(), - style: ProfileStyle( - avatarTextStyle: const TextStyle(fontSize: 20), - pagePadding: EdgeInsets.only( - top: 50, - bottom: 50, - left: MediaQuery.of(context).size.width * 0.1, - right: MediaQuery.of(context).size.width * 0.1, ), - ), + const Text('test') + ], ), ), ); @@ -127,7 +134,7 @@ class CustomItemBuilderExample extends ItemBuilder { options.inputDecorationField?[key] ?? options.inputDecoration; var formFieldKey = GlobalKey(); return SizedBox( - width: 300, + width: 400, child: TextFormField( keyboardType: options.keyboardType?[key], key: formFieldKey, diff --git a/example/lib/utils/example_profile_data.dart b/example/lib/utils/example_profile_data.dart index ff94dcc..8c569ca 100644 --- a/example/lib/utils/example_profile_data.dart +++ b/example/lib/utils/example_profile_data.dart @@ -8,9 +8,13 @@ import 'package:flutter_profile/flutter_profile.dart'; class ExampleProfileData extends ProfileData { ExampleProfileData({ this.email, + this.about, + this.remarks, }); String? email; + String? about; + String? remarks; @override Map mapWidget( @@ -19,6 +23,8 @@ class ExampleProfileData extends ProfileData { ) { return { 'email': null, + 'about': null, + 'remarks': null, }; } @@ -26,14 +32,14 @@ class ExampleProfileData extends ProfileData { ProfileData fromMap(Map data) { return ExampleProfileData( email: data['email'], + about: data['about'], + remarks: data['remarks'], ); } @override Map toMap() { - return { - 'email': email, - }; + return {'email': email, 'about': about, 'remarks': remarks}; } @override diff --git a/example/pubspec.lock b/example/pubspec.lock index 0baa99e..b6c97d3 100644 --- a/example/pubspec.lock +++ b/example/pubspec.lock @@ -124,7 +124,7 @@ packages: path: ".." relative: true source: path - version: "1.0.1" + version: "1.0.2" flutter_test: dependency: "direct dev" description: flutter diff --git a/lib/src/widgets/item_builder/item_list.dart b/lib/src/widgets/item_builder/item_list.dart index f219475..e7c4b47 100644 --- a/lib/src/widgets/item_builder/item_list.dart +++ b/lib/src/widgets/item_builder/item_list.dart @@ -6,81 +6,57 @@ import 'package:flutter/material.dart'; import 'package:flutter_profile/src/widgets/item_builder/item_builder.dart'; import 'package:flutter_profile/src/widgets/item_builder/item_builder_options.dart'; -class ItemList extends StatefulWidget { - const ItemList( +class ItemList { + ItemList( this.items, this.typeMap, - this.spacing, this.updateProfile, this.saveProfile, { required this.formKey, this.itemBuilder, this.itemBuilderOptions, - super.key, - }); + }) { + for (var item in items.entries) { + widgets.addAll({ + item.key: itemBuilder == null + ? builder.build( + item.key, + item.value, + typeMap[item.key], + (value) { + saveProfile(); + }, + (value) { + updateProfile(item.key, value); + }, + ) + : itemBuilder!.build( + item.key, + item.value, + typeMap[item.key], + (value) { + saveProfile(); + }, + (value) { + updateProfile(item.key, value); + }, + ) + }); + } + } + Map getItemList() => widgets; final Map items; final Map typeMap; - final double spacing; final Function(String, String?) updateProfile; final Function() saveProfile; final ItemBuilder? itemBuilder; final ItemBuilderOptions? itemBuilderOptions; final GlobalKey formKey; - @override - State createState() => _ItemListState(); -} - -class _ItemListState extends State { - var widgets = []; + Map widgets = {}; late ItemBuilder builder = ItemBuilder( - options: widget.itemBuilderOptions ?? ItemBuilderOptions(), + options: itemBuilderOptions ?? ItemBuilderOptions(), ); - - @override - void initState() { - super.initState(); - - for (var item in widget.items.entries) { - widget.itemBuilder == null - ? widgets.add( - builder.build( - item.key, - item.value, - widget.typeMap[item.key], - (value) { - widget.saveProfile(); - }, - (value) { - widget.updateProfile(item.key, value); - }, - ), - ) - : widgets.add( - widget.itemBuilder!.build( - item.key, - item.value, - widget.typeMap[item.key], - (value) { - widget.saveProfile(); - }, - (value) { - widget.updateProfile(item.key, value); - }, - ), - ); - widgets.add(SizedBox( - height: widget.spacing, - )); - } - } - - @override - Widget build(BuildContext context) { - return Column( - children: widgets, - ); - } } diff --git a/lib/src/widgets/profile/profile_page.dart b/lib/src/widgets/profile/profile_page.dart index c1c691a..42e6b9b 100644 --- a/lib/src/widgets/profile/profile_page.dart +++ b/lib/src/widgets/profile/profile_page.dart @@ -35,6 +35,7 @@ class ProfilePage extends StatefulWidget { this.style = const ProfileStyle(), this.customAvatar, this.showAvatar = true, + this.showItems = true, this.itemBuilder, this.itemBuilderOptions, this.bottomActionText, @@ -42,6 +43,8 @@ class ProfilePage extends StatefulWidget { this.showDefaultItems = true, this.wrapItemsBuilder, this.wrapViewOptions, + this.extraWidgets, + this.formKey, }) : super(key: key); /// User containing all the user data. @@ -59,6 +62,9 @@ class ProfilePage extends StatefulWidget { /// Whether to show the users avatar. final bool showAvatar; + /// 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. final String? bottomActionText; @@ -80,6 +86,12 @@ 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. + final Map? extraWidgets; + + /// Use the form key to save on any custom callback + final GlobalKey? formKey; + @override State createState() => _ProfilePageState(); } @@ -96,6 +108,7 @@ class _ProfilePageState extends State { style: widget.style, customAvatar: widget.customAvatar, showAvatar: widget.showAvatar, + showItems: widget.showItems, bottomActionText: widget.bottomActionText, itemBuilder: widget.itemBuilder, itemBuilderOptions: widget.itemBuilderOptions, @@ -103,15 +116,22 @@ class _ProfilePageState extends State { showDefaultItems: widget.showDefaultItems, wrapItemsBuilder: widget.wrapItemsBuilder, wrapViewOptions: widget.wrapViewOptions, + extraWidgets: widget.extraWidgets, + formKey: widget.formKey, ); } } class WrapViewOptions { WrapViewOptions( - {this.direction, this.spacing, this.runSpacing, this.clipBehavior}); + {this.direction, + this.spacing, + this.wrapAlignment, + this.runSpacing, + this.clipBehavior}); Axis? direction; double? spacing; double? runSpacing; Clip? clipBehavior; + WrapAlignment? wrapAlignment; } diff --git a/lib/src/widgets/profile/profile_wrapper.dart b/lib/src/widgets/profile/profile_wrapper.dart index 3ec9fcb..02175a1 100644 --- a/lib/src/widgets/profile/profile_wrapper.dart +++ b/lib/src/widgets/profile/profile_wrapper.dart @@ -26,7 +26,10 @@ class ProfileWrapper extends StatefulWidget { this.bottomActionText, this.prioritizedItems = const [], this.showDefaultItems = true, + this.showItems = true, this.wrapItemsBuilder, + this.formKey, + this.extraWidgets, super.key, }); @@ -41,7 +44,10 @@ class ProfileWrapper extends StatefulWidget { final Function rebuild; final ItemBuilderOptions? itemBuilderOptions; final bool showDefaultItems; + final bool showItems; final Widget Function(BuildContext context, Widget child)? wrapItemsBuilder; + final Map? extraWidgets; + final GlobalKey? formKey; /// Map keys of items that should be shown first before the default items and the rest of the items. final List prioritizedItems; @@ -51,161 +57,128 @@ class ProfileWrapper extends StatefulWidget { } class _ProfileWrapperState extends State { - List defaultItems = []; - GlobalKey formKey = GlobalKey(); + late Map widgets = {}; + Map defaultItems = {}; + late GlobalKey _formKey; Map formValues = {}; bool _isUploadingImage = false; late final Widget child; @override void initState() { + _formKey = widget.formKey ?? GlobalKey(); + super.initState(); - if (widget.itemBuilder == null) { - ItemBuilder builder = ItemBuilder( - options: widget.itemBuilderOptions ?? ItemBuilderOptions(), - ); - defaultItems.add( - builder.build( - 'first_name', - widget.user.firstName, - null, - (value) { - submitAllChangedFields(); - }, - (v) { - if (widget.user.firstName != v) { - widget.user.firstName = v; - widget.service.editProfile(widget.user, 'first_name', v); - } - }, - ), - ); - defaultItems.add( - SizedBox( - height: widget.style.betweenDefaultItemPadding, - ), - ); - defaultItems.add( - builder.build( - 'last_name', - widget.user.lastName, - null, - (value) { - submitAllChangedFields(); - }, - (v) { - if (widget.user.lastName != v) { - widget.user.lastName = v; - widget.service.editProfile(widget.user, 'last_name', v); - } - }, - ), - ); - defaultItems.add( - SizedBox( - height: widget.style.betweenDefaultItemPadding, - ), - ); - } else { - defaultItems.add( - widget.itemBuilder!.build( - 'first_name', - widget.user.firstName, - null, - (value) { - submitAllChangedFields(); - }, - (v) { - if (widget.user.firstName != v) { - widget.user.firstName = v; - widget.service.editProfile(widget.user, 'first_name', v); - } - }, - ), - ); - defaultItems.add( - SizedBox( - height: widget.style.betweenDefaultItemPadding, - ), - ); - defaultItems.add( - widget.itemBuilder!.build( - 'last_name', - widget.user.lastName, - null, - (value) { - submitAllChangedFields(); - }, - (v) { - if (widget.user.lastName != v) { - widget.user.lastName = v; - widget.service.editProfile(widget.user, 'last_name', v); - } - }, - ), - ); - defaultItems.add( - SizedBox( - height: widget.style.betweenDefaultItemPadding, - ), - ); + if (widget.showDefaultItems) { + if (widget.itemBuilder == null) { + ItemBuilder builder = ItemBuilder( + options: widget.itemBuilderOptions ?? ItemBuilderOptions(), + ); + defaultItems.addAll({ + 'first_name': builder.build( + 'first_name', + widget.user.firstName, + null, + (value) { + submitAllChangedFields(); + }, + (v) { + if (widget.user.firstName != v) { + widget.user.firstName = v; + widget.service.editProfile(widget.user, 'first_name', v); + } + }, + ), + 'last_name': builder.build( + 'last_name', + widget.user.lastName, + null, + (value) { + submitAllChangedFields(); + }, + (v) { + if (widget.user.lastName != v) { + widget.user.lastName = v; + widget.service.editProfile(widget.user, 'last_name', v); + } + }, + ), + }); + } else { + defaultItems.addAll({ + 'first_name': widget.itemBuilder!.build( + 'first_name', + widget.user.firstName, + null, + (value) { + submitAllChangedFields(); + }, + (v) { + if (widget.user.firstName != v) { + widget.user.firstName = v; + widget.service.editProfile(widget.user, 'first_name', v); + } + }, + ), + 'last_name': widget.itemBuilder!.build( + 'last_name', + widget.user.lastName, + null, + (value) { + submitAllChangedFields(); + }, + (v) { + if (widget.user.lastName != v) { + widget.user.lastName = v; + widget.service.editProfile(widget.user, 'last_name', v); + } + }, + ), + }); + } } + widgets.addAll(widget.extraWidgets ?? {}); + widgets.addAll(defaultItems); + widgets.addAll(ItemList( + Map.fromEntries(widget.user.profileData!.toMap().entries), + widget.user.profileData!.mapWidget( + () { + widget.rebuild(); + }, + context, + ), + (key, value) { + if (widget.user.toMap()['profile_data'][key] == null) { + widget.service.editProfile(widget.user, key, value); + } else if (widget.user.toMap()['profile_data'][key] != value) { + widget.service.editProfile(widget.user, key, value); + } + }, + () { + submitAllChangedFields(); + }, + itemBuilder: widget.itemBuilder, + itemBuilderOptions: widget.itemBuilderOptions, + formKey: _formKey, + ).getItemList()); + var items = Wrap( + alignment: widget.wrapViewOptions?.wrapAlignment ?? WrapAlignment.start, direction: widget.wrapViewOptions?.direction ?? Axis.vertical, spacing: widget.wrapViewOptions?.spacing ?? 0, runSpacing: widget.wrapViewOptions?.runSpacing ?? 0, clipBehavior: widget.wrapViewOptions?.clipBehavior ?? Clip.none, children: [ - ItemList( - Map.fromEntries(widget.user.profileData!.toMap().entries.where( - (element) => widget.prioritizedItems.contains(element.key))), - widget.user.profileData!.mapWidget( - () { - widget.rebuild(); - }, - context, - ), - widget.style.betweenDefaultItemPadding, - (key, value) { - if (widget.user.toMap()['profile_data'][key] == null) { - widget.service.editProfile(widget.user, key, value); - } else if (widget.user.toMap()['profile_data'][key] != value) { - widget.service.editProfile(widget.user, key, value); - } - }, - () { - submitAllChangedFields(); - }, - itemBuilder: widget.itemBuilder, - itemBuilderOptions: widget.itemBuilderOptions, - formKey: formKey, - ), - if (widget.showDefaultItems) ...defaultItems, - // remove all the items that have priority from the widget.user.profileData!.toMap() - ItemList( - Map.fromEntries(widget.user.profileData!.toMap().entries.where( - (element) => !widget.prioritizedItems.contains(element.key))), - widget.user.profileData!.mapWidget( - () { - widget.rebuild(); - }, - context, - ), - widget.style.betweenDefaultItemPadding, - (key, value) { - if (widget.user.toMap()['profile_data'][key] == null) { - widget.service.editProfile(widget.user, key, value); - } else if (widget.user.toMap()['profile_data'][key] != value) { - widget.service.editProfile(widget.user, key, value); - } - }, - () { - submitAllChangedFields(); - }, - itemBuilder: widget.itemBuilder, - itemBuilderOptions: widget.itemBuilderOptions, - formKey: formKey, - ), + //add all items with prio then those without + for (var key in widget.prioritizedItems) + // get values from widgets with this key + ...widgets.entries + .where((element) => element.key == key) + .map((e) => e.value), + + ...widgets.entries + .where((element) => !widget.prioritizedItems.contains(element.key)) + .map((e) => e.value), ], ); @@ -250,8 +223,7 @@ class _ProfileWrapperState extends State { height: widget.style.betweenDefaultItemPadding, ), ], - // all the items that have priority above the default items - Form(key: formKey, child: child), + if (widget.showItems) Form(key: _formKey, child: child), if (widget.bottomActionText != null) ...[ SizedBox( height: widget.style.betweenDefaultItemPadding, @@ -280,8 +252,8 @@ class _ProfileWrapperState extends State { /// This calls onSaved on all the fiels which check if they have a new value void submitAllChangedFields() { - if (formKey.currentState!.validate()) { - formKey.currentState!.save(); + if (_formKey.currentState!.validate()) { + _formKey.currentState!.save(); } } } diff --git a/pubspec.yaml b/pubspec.yaml index b270ab8..f73ff48 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,6 +1,6 @@ name: flutter_profile description: Flutter profile package -version: 1.0.1 +version: 1.0.2 repository: https://github.com/Iconica-Development/flutter_profile environment: