mirror of
https://github.com/Iconica-Development/flutter_profile.git
synced 2025-05-19 01:03:45 +02:00
first test version
Functionality has been added and is working. No test or documentation has been written yet.
This commit is contained in:
parent
ce4054f478
commit
38b076416f
9 changed files with 129 additions and 94 deletions
|
@ -58,8 +58,8 @@ class MyProfileService extends ProfileService {
|
|||
}
|
||||
|
||||
@override
|
||||
uploadImage() {
|
||||
return super.uploadImage();
|
||||
uploadImage(context) {
|
||||
return super.uploadImage(context);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -73,40 +73,38 @@ class MyProfileData extends ProfileData {
|
|||
int justMyString;
|
||||
|
||||
@override
|
||||
Map<String, dynamic> mapWidget(Function update) {
|
||||
Map<String, dynamic> mapWidget(Function update, BuildContext context) {
|
||||
return {
|
||||
'justMyString': Container(
|
||||
'justMyString': SizedBox(
|
||||
height: 100,
|
||||
width: 300,
|
||||
child: Row(
|
||||
children: [
|
||||
ElevatedButton(
|
||||
style: ElevatedButton.styleFrom(
|
||||
primary: justMyString == 1 ? Colors.green : Colors.blue,
|
||||
backgroundColor: justMyString == 1 ? Colors.green : Colors.blue,
|
||||
),
|
||||
onPressed: () {
|
||||
justMyString = 1;
|
||||
update();
|
||||
print(justMyString);
|
||||
},
|
||||
child: const Text('1'),
|
||||
),
|
||||
const Spacer(),
|
||||
ElevatedButton(
|
||||
style: ElevatedButton.styleFrom(
|
||||
primary: justMyString == 2 ? Colors.green : Colors.blue,
|
||||
backgroundColor: justMyString == 2 ? Colors.green : Colors.blue,
|
||||
),
|
||||
onPressed: () {
|
||||
justMyString = 2;
|
||||
update();
|
||||
print(justMyString);
|
||||
},
|
||||
child: const Text('2'),
|
||||
),
|
||||
const Spacer(),
|
||||
ElevatedButton(
|
||||
style: ElevatedButton.styleFrom(
|
||||
primary: justMyString == 3 ? Colors.green : Colors.blue,
|
||||
backgroundColor: justMyString == 3 ? Colors.green : Colors.blue,
|
||||
),
|
||||
onPressed: () {
|
||||
justMyString = 3;
|
||||
|
@ -117,7 +115,7 @@ class MyProfileData extends ProfileData {
|
|||
const Spacer(),
|
||||
ElevatedButton(
|
||||
style: ElevatedButton.styleFrom(
|
||||
primary: justMyString == 4 ? Colors.green : Colors.blue,
|
||||
backgroundColor: justMyString == 4 ? Colors.green : Colors.blue,
|
||||
),
|
||||
onPressed: () {
|
||||
justMyString = 4;
|
||||
|
|
|
@ -7,7 +7,7 @@ packages:
|
|||
name: async
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.8.2"
|
||||
version: "2.9.0"
|
||||
boolean_selector:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -21,21 +21,14 @@ packages:
|
|||
name: characters
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.2.0"
|
||||
charcode:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: charcode
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.3.1"
|
||||
version: "1.2.1"
|
||||
clock:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: clock
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.1.0"
|
||||
version: "1.1.1"
|
||||
collection:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -56,7 +49,7 @@ packages:
|
|||
name: fake_async
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.3.0"
|
||||
version: "1.3.1"
|
||||
flutter:
|
||||
dependency: "direct main"
|
||||
description: flutter
|
||||
|
@ -87,28 +80,28 @@ packages:
|
|||
name: matcher
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.12.11"
|
||||
version: "0.12.12"
|
||||
material_color_utilities:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: material_color_utilities
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.1.4"
|
||||
version: "0.1.5"
|
||||
meta:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: meta
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.7.0"
|
||||
version: "1.8.0"
|
||||
path:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: path
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.8.1"
|
||||
version: "1.8.2"
|
||||
profile:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
|
@ -127,7 +120,7 @@ packages:
|
|||
name: source_span
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.8.2"
|
||||
version: "1.9.0"
|
||||
stack_trace:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -148,21 +141,21 @@ packages:
|
|||
name: string_scanner
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.1.0"
|
||||
version: "1.1.1"
|
||||
term_glyph:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: term_glyph
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.2.0"
|
||||
version: "1.2.1"
|
||||
test_api:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: test_api
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.4.9"
|
||||
version: "0.4.12"
|
||||
vector_math:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
library profile;
|
||||
|
||||
export 'src/widgets/profile/profile_page.dart';
|
||||
export 'src/widgets/profile/profile_style.dart';
|
||||
export 'src/widgets/avatar/avatar_style.dart';
|
||||
export 'src/services/profile_service.dart';
|
||||
export 'src/widgets/item_builder/item_builder.dart';
|
||||
export 'src/models/user.dart';
|
||||
export 'src/widgets/item_builder/item_builder_options.dart';
|
||||
|
|
|
@ -2,8 +2,6 @@ import 'dart:typed_data';
|
|||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:profile/profile.dart';
|
||||
import 'package:profile/src/widgets/item_builder/item_builder.dart';
|
||||
import 'package:profile/src/widgets/item_builder/item_builder_options.dart';
|
||||
|
||||
class User<T extends ProfileData> {
|
||||
String? firstName;
|
||||
|
@ -44,7 +42,7 @@ abstract class ProfileData {
|
|||
|
||||
Map<String, dynamic> toMap();
|
||||
|
||||
Map<String, dynamic> mapWidget(Function update);
|
||||
Map<String, dynamic> mapWidget(VoidCallback update, BuildContext context);
|
||||
|
||||
ProfileData create();
|
||||
|
||||
|
@ -58,12 +56,13 @@ abstract class ProfileData {
|
|||
}) {
|
||||
var widgets = <Widget>[];
|
||||
ItemBuilder builder = ItemBuilder(
|
||||
options: itemBuilderOptions ?? const ItemBuilderOptions(),
|
||||
options: itemBuilderOptions ?? ItemBuilderOptions(),
|
||||
);
|
||||
for (var item in items.entries) {
|
||||
itemBuilder == null
|
||||
? widgets.add(
|
||||
builder.build(
|
||||
item.key,
|
||||
item.value,
|
||||
typeMap[item.key],
|
||||
(value) {
|
||||
|
@ -73,6 +72,7 @@ abstract class ProfileData {
|
|||
)
|
||||
: widgets.add(
|
||||
itemBuilder.build(
|
||||
item.key,
|
||||
item.value,
|
||||
typeMap[item.key],
|
||||
(value) {
|
||||
|
|
|
@ -1,12 +1,10 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:profile/profile.dart';
|
||||
|
||||
abstract class ProfileService {
|
||||
const ProfileService();
|
||||
|
||||
deleteProfile() {
|
||||
print("Request to delete profile");
|
||||
// TODO(anyone) project specific
|
||||
}
|
||||
deleteProfile() {}
|
||||
|
||||
editProfile<T extends ProfileData>(User user, String key, String value) {
|
||||
if (user.profileData != null) {
|
||||
|
@ -19,8 +17,5 @@ abstract class ProfileService {
|
|||
}
|
||||
}
|
||||
|
||||
uploadImage() {
|
||||
print('Request to change picture');
|
||||
// TODO(anyone) open image picker and update profile
|
||||
}
|
||||
uploadImage(BuildContext context) async {}
|
||||
}
|
||||
|
|
|
@ -7,13 +7,15 @@ class Avatar extends StatelessWidget {
|
|||
const Avatar({
|
||||
Key? key,
|
||||
this.image,
|
||||
this.name,
|
||||
this.firstName,
|
||||
this.lastName,
|
||||
this.avatar,
|
||||
this.style = const AvatarStyle(),
|
||||
}) : super(key: key);
|
||||
|
||||
final Uint8List? image;
|
||||
final String? name;
|
||||
final String? firstName;
|
||||
final String? lastName;
|
||||
final Widget? avatar;
|
||||
final AvatarStyle style;
|
||||
|
||||
|
@ -22,9 +24,12 @@ class Avatar extends StatelessWidget {
|
|||
return Column(
|
||||
children: [
|
||||
_avatar(),
|
||||
if (name != null)
|
||||
const SizedBox(
|
||||
height: 16,
|
||||
),
|
||||
if (firstName != null || lastName != null)
|
||||
Text(
|
||||
name!,
|
||||
'${firstName ?? ''} ${lastName ?? ''}',
|
||||
style: style.displayNameStyle,
|
||||
)
|
||||
],
|
||||
|
@ -39,22 +44,26 @@ class Avatar extends StatelessWidget {
|
|||
return Container(
|
||||
width: style.width,
|
||||
height: style.height,
|
||||
decoration: const BoxDecoration(
|
||||
decoration: BoxDecoration(
|
||||
shape: BoxShape.circle,
|
||||
image: DecorationImage(
|
||||
image: MemoryImage(image!),
|
||||
fit: BoxFit.fill,
|
||||
),
|
||||
),
|
||||
child: Image.memory(image!),
|
||||
);
|
||||
} else if (name != null && name!.isNotEmpty) {
|
||||
} else if (firstName != null || lastName != null) {
|
||||
return Container(
|
||||
width: style.width,
|
||||
height: style.height,
|
||||
decoration: BoxDecoration(
|
||||
color: _generateColorWithIntials(name!),
|
||||
color: _generateColorWithIntials(firstName, lastName),
|
||||
shape: BoxShape.circle,
|
||||
),
|
||||
child: Center(
|
||||
child: Text(
|
||||
_getInitials(name!),
|
||||
style: const TextStyle(fontSize: 40),
|
||||
_getInitials(firstName, lastName),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
@ -67,15 +76,13 @@ class Avatar extends StatelessWidget {
|
|||
}
|
||||
}
|
||||
|
||||
String _getInitials(String name) {
|
||||
var nameList = name.split(' ');
|
||||
return nameList.first[0] + nameList.last[0];
|
||||
String _getInitials(String? firstName, String? lastName) {
|
||||
return (firstName?[0] ?? '') + (lastName?[0] ?? '');
|
||||
}
|
||||
|
||||
Color _generateColorWithIntials(String name) {
|
||||
var nameList = name.split(' ');
|
||||
var uniqueInitialId = nameList.first.toLowerCase().codeUnitAt(0) +
|
||||
nameList.last.toLowerCase().codeUnitAt(0);
|
||||
Color _generateColorWithIntials(String? firstName, String? lastName) {
|
||||
var uniqueInitialId = (firstName?.toLowerCase().codeUnitAt(0) ?? 0) +
|
||||
(lastName?.toLowerCase().codeUnitAt(0) ?? 0);
|
||||
|
||||
return Colors.primaries[uniqueInitialId % Colors.primaries.length];
|
||||
}
|
||||
|
|
|
@ -8,19 +8,42 @@ class ItemBuilder {
|
|||
|
||||
final ItemBuilderOptions options;
|
||||
|
||||
Widget build(dynamic value, Widget? widget, Function(String) updateItem) {
|
||||
Widget build(
|
||||
String key, dynamic value, Widget? widget, Function(String) updateItem) {
|
||||
if (widget == null) {
|
||||
var controller = TextEditingController(
|
||||
text: '$value',
|
||||
text: '${value ?? ''}',
|
||||
);
|
||||
|
||||
return TextField(
|
||||
controller: controller,
|
||||
decoration: options.inputDecoration,
|
||||
readOnly: options.readOnly,
|
||||
onSubmitted: (s) {
|
||||
updateItem(s);
|
||||
},
|
||||
late InputDecoration inputDecoration;
|
||||
if (options.inputDecorationField != null &&
|
||||
options.inputDecorationField![key] != null) {
|
||||
inputDecoration = options.inputDecorationField![key]!;
|
||||
} else {
|
||||
inputDecoration = options.inputDecoration;
|
||||
}
|
||||
|
||||
final formKey = GlobalKey<FormState>();
|
||||
|
||||
return Form(
|
||||
key: formKey,
|
||||
child: TextFormField(
|
||||
controller: controller,
|
||||
decoration: inputDecoration,
|
||||
readOnly: options.readOnly,
|
||||
onFieldSubmitted: (value) {
|
||||
if (formKey.currentState!.validate()) {
|
||||
updateItem(value);
|
||||
}
|
||||
},
|
||||
validator: (value) {
|
||||
if (options.validators != null &&
|
||||
options.validators![key] != null) {
|
||||
return options.validators![key]!(value);
|
||||
}
|
||||
return null;
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
return widget;
|
||||
|
|
|
@ -1,11 +1,15 @@
|
|||
import 'package:flutter/material.dart';
|
||||
|
||||
class ItemBuilderOptions {
|
||||
const ItemBuilderOptions({
|
||||
ItemBuilderOptions({
|
||||
this.inputDecoration = const InputDecoration(),
|
||||
this.inputDecorationField,
|
||||
this.readOnly = false,
|
||||
this.validators,
|
||||
});
|
||||
|
||||
final InputDecoration inputDecoration;
|
||||
final Map<String, InputDecoration>? inputDecorationField;
|
||||
final bool readOnly;
|
||||
final Map<String, String? Function(String?)>? validators;
|
||||
}
|
||||
|
|
|
@ -1,9 +1,6 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:profile/profile.dart';
|
||||
import 'package:profile/src/widgets/avatar/avatar.dart';
|
||||
import 'package:profile/src/widgets/item_builder/item_builder_options.dart';
|
||||
|
||||
import 'package:profile/src/widgets/profile/profile_style.dart';
|
||||
|
||||
class ProfilePage extends StatefulWidget {
|
||||
const ProfilePage({
|
||||
|
@ -81,52 +78,50 @@ class ProfileWrapper extends StatefulWidget {
|
|||
}
|
||||
|
||||
class _ProfileWrapperState extends State<ProfileWrapper> {
|
||||
late List<Widget> profileItems;
|
||||
List<Widget> defaultItems = [];
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
profileItems = widget.user.profileData!.buildItems(
|
||||
widget.user.profileData!.toMap(),
|
||||
widget.user.profileData!.mapWidget(() {
|
||||
widget.rebuild();
|
||||
}),
|
||||
widget.style.betweenDefaultItemPadding,
|
||||
(key, value) {
|
||||
widget.service.editProfile(widget.user, key, value);
|
||||
},
|
||||
itemBuilder: widget.itemBuilder,
|
||||
itemBuilderOptions: widget.itemBuilderOptions,
|
||||
);
|
||||
|
||||
if (widget.itemBuilder == null) {
|
||||
ItemBuilder builder = ItemBuilder(
|
||||
options: widget.itemBuilderOptions ?? const ItemBuilderOptions(),
|
||||
options: widget.itemBuilderOptions ?? ItemBuilderOptions(),
|
||||
);
|
||||
defaultItems.add(builder.build(widget.user.firstName, null, (v) {
|
||||
defaultItems
|
||||
.add(builder.build('firstName', widget.user.firstName, null, (v) {
|
||||
widget.user.firstName = v;
|
||||
|
||||
widget.service.editProfile(widget.user, 'firstName', v);
|
||||
}));
|
||||
defaultItems.add(
|
||||
SizedBox(
|
||||
height: widget.style.betweenDefaultItemPadding,
|
||||
),
|
||||
);
|
||||
defaultItems.add(builder.build(widget.user.lastName, null, (v) {
|
||||
defaultItems
|
||||
.add(builder.build('lastName', widget.user.lastName, null, (v) {
|
||||
widget.user.lastName = v;
|
||||
|
||||
widget.service.editProfile(widget.user, 'lastName', v);
|
||||
}));
|
||||
} else {
|
||||
defaultItems
|
||||
.add(widget.itemBuilder!.build(widget.user.firstName, null, (v) {
|
||||
defaultItems.add(widget.itemBuilder!
|
||||
.build('firstName', widget.user.firstName, null, (v) {
|
||||
widget.user.firstName = v;
|
||||
|
||||
widget.service.editProfile(widget.user, 'firstname', v);
|
||||
}));
|
||||
defaultItems.add(
|
||||
SizedBox(
|
||||
height: widget.style.betweenDefaultItemPadding,
|
||||
),
|
||||
);
|
||||
defaultItems
|
||||
.add(widget.itemBuilder!.build(widget.user.lastName, null, (v) {
|
||||
defaultItems.add(widget.itemBuilder!
|
||||
.build('lastName', widget.user.lastName, null, (v) {
|
||||
widget.user.lastName = v;
|
||||
|
||||
widget.service.editProfile(widget.user, 'lastName', v);
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
@ -134,17 +129,19 @@ class _ProfileWrapperState extends State<ProfileWrapper> {
|
|||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Material(
|
||||
color: Colors.transparent,
|
||||
child: Padding(
|
||||
padding: widget.style.pagePadding,
|
||||
child: Column(
|
||||
children: [
|
||||
if (widget.showAvatar)
|
||||
InkWell(
|
||||
onTap: () {
|
||||
widget.service.uploadImage();
|
||||
onTap: () async {
|
||||
await widget.service.uploadImage(context);
|
||||
},
|
||||
child: Avatar(
|
||||
name: '${widget.user.firstName} ${widget.user.lastName}',
|
||||
firstName: widget.user.firstName,
|
||||
lastName: widget.user.lastName,
|
||||
style: widget.style.avatarStyle,
|
||||
avatar: widget.customAvatar,
|
||||
image: widget.user.image,
|
||||
|
@ -155,11 +152,26 @@ class _ProfileWrapperState extends State<ProfileWrapper> {
|
|||
height: widget.style.betweenDefaultItemPadding,
|
||||
),
|
||||
...defaultItems,
|
||||
...profileItems,
|
||||
...widget.user.profileData!.buildItems(
|
||||
widget.user.profileData!.toMap(),
|
||||
widget.user.profileData!.mapWidget(
|
||||
() {
|
||||
widget.rebuild();
|
||||
},
|
||||
context,
|
||||
),
|
||||
widget.style.betweenDefaultItemPadding,
|
||||
(key, value) {
|
||||
widget.service.editProfile(widget.user, key, value);
|
||||
},
|
||||
itemBuilder: widget.itemBuilder,
|
||||
itemBuilderOptions: widget.itemBuilderOptions,
|
||||
),
|
||||
if (widget.showDeleteProfile)
|
||||
SizedBox(
|
||||
height: widget.style.betweenDefaultItemPadding,
|
||||
),
|
||||
const Spacer(),
|
||||
if (widget.showDeleteProfile)
|
||||
InkWell(
|
||||
onTap: () {
|
||||
|
|
Loading…
Reference in a new issue