mirror of
https://github.com/Iconica-Development/flutter_timeline.git
synced 2025-05-19 10:33:44 +02:00
feat:add namebuilder
This commit is contained in:
parent
03b14924a2
commit
d60244fa3e
5 changed files with 180 additions and 108 deletions
|
@ -26,6 +26,7 @@ class TimelinePost {
|
|||
this.reactions,
|
||||
this.imageUrl,
|
||||
this.image,
|
||||
this.data = const {},
|
||||
});
|
||||
|
||||
factory TimelinePost.fromJson(String id, Map<String, dynamic> json) =>
|
||||
|
@ -50,6 +51,7 @@ class TimelinePost {
|
|||
.toList(),
|
||||
createdAt: DateTime.parse(json['created_at'] as String),
|
||||
reactionEnabled: json['reaction_enabled'] as bool,
|
||||
data: json['data'] ?? {},
|
||||
);
|
||||
|
||||
/// The unique identifier of the post.
|
||||
|
@ -94,6 +96,9 @@ class TimelinePost {
|
|||
/// If reacting is enabled on the post.
|
||||
final bool reactionEnabled;
|
||||
|
||||
/// Option to add extra data to a timelinepost that won't be shown anywhere
|
||||
final Map<String, dynamic> data;
|
||||
|
||||
TimelinePost copyWith({
|
||||
String? id,
|
||||
String? creatorId,
|
||||
|
@ -109,6 +114,7 @@ class TimelinePost {
|
|||
List<TimelinePostReaction>? reactions,
|
||||
DateTime? createdAt,
|
||||
bool? reactionEnabled,
|
||||
Map<String, dynamic>? data,
|
||||
}) =>
|
||||
TimelinePost(
|
||||
id: id ?? this.id,
|
||||
|
@ -125,6 +131,7 @@ class TimelinePost {
|
|||
reactions: reactions ?? this.reactions,
|
||||
createdAt: createdAt ?? this.createdAt,
|
||||
reactionEnabled: reactionEnabled ?? this.reactionEnabled,
|
||||
data: data ?? this.data,
|
||||
);
|
||||
|
||||
Map<String, dynamic> toJson() => {
|
||||
|
@ -140,5 +147,6 @@ class TimelinePost {
|
|||
'reactions': reactions?.map((e) => e.toJson()).toList() ?? [],
|
||||
'created_at': createdAt.toIso8601String(),
|
||||
'reaction_enabled': reactionEnabled,
|
||||
'data': data,
|
||||
};
|
||||
}
|
||||
|
|
|
@ -24,6 +24,8 @@ class TimelineOptions {
|
|||
this.buttonBuilder,
|
||||
this.textInputBuilder,
|
||||
this.userAvatarBuilder,
|
||||
this.anonymousAvatarBuilder,
|
||||
this.nameBuilder,
|
||||
});
|
||||
|
||||
/// Theming options for the timeline
|
||||
|
@ -56,6 +58,12 @@ class TimelineOptions {
|
|||
|
||||
final UserAvatarBuilder? userAvatarBuilder;
|
||||
|
||||
/// When the imageUrl is null this anonymousAvatarBuilder will be used
|
||||
/// You can use it to display a default avatarW
|
||||
final UserAvatarBuilder? anonymousAvatarBuilder;
|
||||
|
||||
final String Function(TimelinePosterUserModel?)? nameBuilder;
|
||||
|
||||
/// ImagePickerTheme can be used to change the UI of the
|
||||
/// Image Picker Widget to change the text/icons to your liking.
|
||||
final ImagePickerTheme imagePickerTheme;
|
||||
|
@ -78,7 +86,7 @@ typedef TextInputBuilder = Widget Function(
|
|||
String hintText,
|
||||
);
|
||||
|
||||
typedef UserAvatarBuilder = Widget Function(
|
||||
typedef UserAvatarBuilder = Widget? Function(
|
||||
TimelinePosterUserModel user,
|
||||
double size,
|
||||
);
|
||||
|
|
|
@ -123,6 +123,7 @@ class _TimelinePostCreationScreenState
|
|||
height: 100,
|
||||
child: TextField(
|
||||
controller: contentController,
|
||||
textCapitalization: TextCapitalization.sentences,
|
||||
expands: true,
|
||||
maxLines: null,
|
||||
minLines: null,
|
||||
|
|
|
@ -153,17 +153,29 @@ class _TimelinePostScreenState extends State<TimelinePostScreen> {
|
|||
post.creator!.imageUrl!,
|
||||
),
|
||||
),
|
||||
] else ...[
|
||||
widget.options.anonymousAvatarBuilder?.call(
|
||||
post.creator!,
|
||||
40,
|
||||
) ??
|
||||
const CircleAvatar(
|
||||
radius: 20,
|
||||
child: Icon(
|
||||
Icons.person,
|
||||
),
|
||||
),
|
||||
],
|
||||
const SizedBox(width: 10),
|
||||
if (post.creator!.fullName != null) ...[
|
||||
Text(
|
||||
post.creator!.fullName!,
|
||||
widget.options.nameBuilder
|
||||
?.call(post.creator) ??
|
||||
post.creator?.fullName ??
|
||||
widget.options.translations.anonymousUser,
|
||||
style: widget.options.theme.textStyles
|
||||
.postCreatorTitleStyle ??
|
||||
theme.textTheme.titleMedium,
|
||||
),
|
||||
],
|
||||
],
|
||||
),
|
||||
),
|
||||
const Spacer(),
|
||||
|
@ -206,19 +218,23 @@ class _TimelinePostScreenState extends State<TimelinePostScreen> {
|
|||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
// image of the post
|
||||
if (post.imageUrl != null) ...[
|
||||
CachedNetworkImage(
|
||||
imageUrl: post.imageUrl!,
|
||||
const SizedBox(height: 8),
|
||||
ClipRRect(
|
||||
borderRadius: const BorderRadius.all(Radius.circular(8)),
|
||||
child: CachedNetworkImage(
|
||||
width: double.infinity,
|
||||
imageUrl: post.imageUrl!,
|
||||
fit: BoxFit.fitHeight,
|
||||
),
|
||||
),
|
||||
],
|
||||
const SizedBox(
|
||||
height: 8,
|
||||
),
|
||||
// post information
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 4.0),
|
||||
child: Row(
|
||||
Row(
|
||||
children: [
|
||||
if (post.likedBy?.contains(widget.userId) ?? false) ...[
|
||||
InkWell(
|
||||
|
@ -262,7 +278,7 @@ class _TimelinePostScreenState extends State<TimelinePostScreen> {
|
|||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
Text(
|
||||
'${post.likes} ${widget.options.translations.likesTitle}',
|
||||
style: widget
|
||||
|
@ -272,7 +288,8 @@ class _TimelinePostScreenState extends State<TimelinePostScreen> {
|
|||
const SizedBox(height: 4),
|
||||
Text.rich(
|
||||
TextSpan(
|
||||
text: post.creator?.fullName ??
|
||||
text: widget.options.nameBuilder?.call(post.creator) ??
|
||||
post.creator?.fullName ??
|
||||
widget.options.translations.anonymousUser,
|
||||
style: widget
|
||||
.options.theme.textStyles.postCreatorNameStyle ??
|
||||
|
@ -287,9 +304,8 @@ class _TimelinePostScreenState extends State<TimelinePostScreen> {
|
|||
),
|
||||
],
|
||||
),
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
const SizedBox(height: 4),
|
||||
const SizedBox(height: 20),
|
||||
Html(
|
||||
data: post.content,
|
||||
style: {
|
||||
|
@ -300,15 +316,20 @@ class _TimelinePostScreenState extends State<TimelinePostScreen> {
|
|||
'#': Style(
|
||||
maxLines: 3,
|
||||
textOverflow: TextOverflow.ellipsis,
|
||||
padding: HtmlPaddings.zero,
|
||||
margin: Margins.zero,
|
||||
),
|
||||
'H1': Style(
|
||||
margin: Margins.all(0),
|
||||
padding: HtmlPaddings.zero,
|
||||
margin: Margins.zero,
|
||||
),
|
||||
'H2': Style(
|
||||
margin: Margins.all(0),
|
||||
padding: HtmlPaddings.zero,
|
||||
margin: Margins.zero,
|
||||
),
|
||||
'H3': Style(
|
||||
margin: Margins.all(0),
|
||||
padding: HtmlPaddings.zero,
|
||||
margin: Margins.zero,
|
||||
),
|
||||
},
|
||||
),
|
||||
|
@ -319,7 +340,7 @@ class _TimelinePostScreenState extends State<TimelinePostScreen> {
|
|||
'${timeFormat.format(post.createdAt)}',
|
||||
style: theme.textTheme.bodySmall,
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
const SizedBox(height: 20),
|
||||
if (post.reactionEnabled) ...[
|
||||
Text(
|
||||
widget.options.translations.commentsTitle,
|
||||
|
@ -381,6 +402,17 @@ class _TimelinePostScreenState extends State<TimelinePostScreen> {
|
|||
reaction.creator!.imageUrl!,
|
||||
),
|
||||
),
|
||||
] else ...[
|
||||
widget.options.anonymousAvatarBuilder?.call(
|
||||
reaction.creator!,
|
||||
25,
|
||||
) ??
|
||||
const CircleAvatar(
|
||||
radius: 20,
|
||||
child: Icon(
|
||||
Icons.person,
|
||||
),
|
||||
),
|
||||
],
|
||||
const SizedBox(width: 10),
|
||||
if (reaction.imageUrl != null) ...[
|
||||
|
@ -389,6 +421,8 @@ class _TimelinePostScreenState extends State<TimelinePostScreen> {
|
|||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
widget.options.nameBuilder
|
||||
?.call(post.creator) ??
|
||||
reaction.creator?.fullName ??
|
||||
widget.options.translations
|
||||
.anonymousUser,
|
||||
|
@ -408,7 +442,9 @@ class _TimelinePostScreenState extends State<TimelinePostScreen> {
|
|||
Expanded(
|
||||
child: Text.rich(
|
||||
TextSpan(
|
||||
text: reaction.creator?.fullName ??
|
||||
text: widget.options.nameBuilder
|
||||
?.call(post.creator) ??
|
||||
reaction.creator?.fullName ??
|
||||
widget
|
||||
.options.translations.anonymousUser,
|
||||
style: theme.textTheme.titleSmall,
|
||||
|
|
|
@ -68,16 +68,27 @@ class TimelinePostWidget extends StatelessWidget {
|
|||
post.creator!.imageUrl!,
|
||||
),
|
||||
),
|
||||
],
|
||||
const SizedBox(width: 10),
|
||||
if (post.creator!.fullName != null) ...[
|
||||
Text(
|
||||
post.creator!.fullName!,
|
||||
style: options.theme.textStyles
|
||||
.listPostCreatorTitleStyle ??
|
||||
theme.textTheme.titleMedium,
|
||||
] else ...[
|
||||
options.anonymousAvatarBuilder?.call(
|
||||
post.creator!,
|
||||
40,
|
||||
) ??
|
||||
const CircleAvatar(
|
||||
radius: 20,
|
||||
child: Icon(
|
||||
Icons.person,
|
||||
),
|
||||
),
|
||||
],
|
||||
const SizedBox(width: 10),
|
||||
Text(
|
||||
options.nameBuilder?.call(post.creator) ??
|
||||
post.creator?.fullName ??
|
||||
options.translations.anonymousUser,
|
||||
style:
|
||||
options.theme.textStyles.postCreatorTitleStyle ??
|
||||
theme.textTheme.titleMedium,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
@ -118,22 +129,26 @@ class TimelinePostWidget extends StatelessWidget {
|
|||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
// image of the post
|
||||
if (post.imageUrl != null) ...[
|
||||
const SizedBox(height: 8),
|
||||
Flexible(
|
||||
flex: height != null ? 1 : 0,
|
||||
child: ClipRRect(
|
||||
borderRadius: const BorderRadius.all(Radius.circular(8)),
|
||||
child: CachedNetworkImage(
|
||||
imageUrl: post.imageUrl!,
|
||||
width: double.infinity,
|
||||
imageUrl: post.imageUrl!,
|
||||
fit: BoxFit.fitWidth,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
const SizedBox(
|
||||
height: 8,
|
||||
),
|
||||
// post information
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 4.0),
|
||||
child: Row(
|
||||
Row(
|
||||
children: [
|
||||
if (post.likedBy?.contains(userId) ?? false) ...[
|
||||
InkWell(
|
||||
|
@ -163,7 +178,10 @@ class TimelinePostWidget extends StatelessWidget {
|
|||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(
|
||||
height: 8,
|
||||
),
|
||||
|
||||
Text(
|
||||
'${post.likes} ${options.translations.likesTitle}',
|
||||
style: options.theme.textStyles.listPostLikeTitleAndAmount ??
|
||||
|
@ -172,7 +190,8 @@ class TimelinePostWidget extends StatelessWidget {
|
|||
const SizedBox(height: 4),
|
||||
Text.rich(
|
||||
TextSpan(
|
||||
text: post.creator?.fullName ??
|
||||
text: options.nameBuilder?.call(post.creator) ??
|
||||
post.creator?.fullName ??
|
||||
options.translations.anonymousUser,
|
||||
style: options.theme.textStyles.listCreatorNameStyle ??
|
||||
theme.textTheme.titleSmall,
|
||||
|
@ -185,8 +204,8 @@ class TimelinePostWidget extends StatelessWidget {
|
|||
),
|
||||
],
|
||||
),
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
const SizedBox(height: 4),
|
||||
Text(
|
||||
options.translations.viewPost,
|
||||
style: options.theme.textStyles.viewPostStyle ??
|
||||
|
|
Loading…
Reference in a new issue