feat: option to delete reactions

This commit is contained in:
Freek van de Ven 2023-12-06 07:01:40 +01:00
parent e523f52118
commit 7e89ba9c85
5 changed files with 115 additions and 51 deletions

View file

@ -28,7 +28,11 @@ class TimelineUserStoryConfiguration {
final Widget Function(BuildContext context, Widget filterBar, Widget child)? final Widget Function(BuildContext context, Widget filterBar, Widget child)?
mainPageBuilder; mainPageBuilder;
final Widget Function(BuildContext context, Widget child, TimelineCategory category)? postScreenBuilder; final Widget Function(
BuildContext context,
Widget child,
TimelineCategory category,
)? postScreenBuilder;
final Widget Function(BuildContext context, Widget child)? final Widget Function(BuildContext context, Widget child)?
postCreationScreenBuilder; postCreationScreenBuilder;

View file

@ -60,6 +60,30 @@ class FirebaseTimelineService with ChangeNotifier implements TimelineService {
notifyListeners(); notifyListeners();
} }
@override
Future<TimelinePost> deletePostReaction(
TimelinePost post,
String reactionId,
) async {
var updatedPost = post.copyWith(
reaction: post.reaction - 1,
reactions: (post.reactions ?? [])
..removeWhere((element) => element.id == reactionId),
);
_posts = _posts
.map(
(p) => p.id == post.id ? updatedPost : p,
)
.toList();
var postRef = _db.collection(_options.timelineCollectionName).doc(post.id);
await postRef.update({
'reaction': FieldValue.increment(-1),
'reactions': FieldValue.arrayRemove([reactionId]),
});
notifyListeners();
return updatedPost;
}
@override @override
Future<TimelinePost> fetchPostDetails(TimelinePost post) async { Future<TimelinePost> fetchPostDetails(TimelinePost post) async {
var reactions = post.reactions ?? []; var reactions = post.reactions ?? [];

View file

@ -10,6 +10,7 @@ import 'package:flutter_timeline_interface/src/model/timeline_reaction.dart';
abstract class TimelineService with ChangeNotifier { abstract class TimelineService with ChangeNotifier {
Future<void> deletePost(TimelinePost post); Future<void> deletePost(TimelinePost post);
Future<TimelinePost> deletePostReaction(TimelinePost post, String reactionId);
Future<TimelinePost> createPost(TimelinePost post); Future<TimelinePost> createPost(TimelinePost post);
Future<List<TimelinePost>> fetchPosts(String? category); Future<List<TimelinePost>> fetchPosts(String? category);
Future<TimelinePost> fetchPost(TimelinePost post); Future<TimelinePost> fetchPost(TimelinePost post);

View file

@ -20,6 +20,7 @@ class TimelineTranslations {
'Indicate whether people are allowed to respond', 'Indicate whether people are allowed to respond',
this.checkPost = 'Check post overview', this.checkPost = 'Check post overview',
this.deletePost = 'Delete post', this.deletePost = 'Delete post',
this.deleteReaction = 'Delete Reaction',
this.viewPost = 'View post', this.viewPost = 'View post',
this.likesTitle = 'Likes', this.likesTitle = 'Likes',
this.commentsTitle = 'Comments', this.commentsTitle = 'Comments',
@ -45,6 +46,7 @@ class TimelineTranslations {
final String postAt; final String postAt;
final String deletePost; final String deletePost;
final String deleteReaction;
final String viewPost; final String viewPost;
final String likesTitle; final String likesTitle;
final String commentsTitle; final String commentsTitle;

View file

@ -312,7 +312,38 @@ class _TimelinePostScreenState extends State<TimelinePostScreen> {
for (var reaction for (var reaction
in post.reactions ?? <TimelinePostReaction>[]) ...[ in post.reactions ?? <TimelinePostReaction>[]) ...[
const SizedBox(height: 16), const SizedBox(height: 16),
Row( GestureDetector(
onLongPress: () async {
if (reaction.creatorId == widget.userId ||
widget.options.allowAllDeletion) {
// Show popup menu for deletion
var value = await showMenu<String>(
context: context,
position: const RelativeRect.fromLTRB(
100.0,
200.0,
100.0,
100.0,
),
items: [
PopupMenuItem<String>(
value: 'delete',
child: Text(
widget.options.translations.deleteReaction,
),
),
],
);
if (value == 'delete') {
// Call service to delete reaction
updatePost(
await widget.service
.deletePostReaction(post, reaction.id),
);
}
}
},
child: Row(
crossAxisAlignment: reaction.imageUrl != null crossAxisAlignment: reaction.imageUrl != null
? CrossAxisAlignment.start ? CrossAxisAlignment.start
: CrossAxisAlignment.center, : CrossAxisAlignment.center,
@ -338,8 +369,8 @@ class _TimelinePostScreenState extends State<TimelinePostScreen> {
children: [ children: [
Text( Text(
reaction.creator?.fullName ?? reaction.creator?.fullName ??
widget widget.options.translations
.options.translations.anonymousUser, .anonymousUser,
style: theme.textTheme.titleSmall, style: theme.textTheme.titleSmall,
), ),
Padding( Padding(
@ -357,7 +388,8 @@ class _TimelinePostScreenState extends State<TimelinePostScreen> {
child: Text.rich( child: Text.rich(
TextSpan( TextSpan(
text: reaction.creator?.fullName ?? text: reaction.creator?.fullName ??
widget.options.translations.anonymousUser, widget
.options.translations.anonymousUser,
style: theme.textTheme.titleSmall, style: theme.textTheme.titleSmall,
children: [ children: [
const TextSpan(text: ' '), const TextSpan(text: ' '),
@ -373,6 +405,7 @@ class _TimelinePostScreenState extends State<TimelinePostScreen> {
], ],
], ],
), ),
),
], ],
if (post.reactions?.isEmpty ?? true) ...[ if (post.reactions?.isEmpty ?? true) ...[
const SizedBox(height: 16), const SizedBox(height: 16),