Skip to content

Commit daf9a6c

Browse files
Merge pull request #14 from SimCoderYoutube/lesson_14/reply_to_a_post
[Add] post reply
2 parents 5a54e16 + 25801f1 commit daf9a6c

File tree

8 files changed

+116
-8
lines changed

8 files changed

+116
-8
lines changed

frontend/lib/models/post.dart

+3-1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ class PostModel {
77
final Timestamp timestamp;
88
final String originalId;
99
final bool retweet;
10+
DocumentReference ref;
1011

1112
int likesCount;
1213
int retweetsCount;
@@ -19,5 +20,6 @@ class PostModel {
1920
this.likesCount,
2021
this.retweetsCount,
2122
this.originalId,
22-
this.retweet});
23+
this.retweet,
24+
this.ref});
2325
}

frontend/lib/screens/home/feed.dart

+1-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ class FeedState extends State<Feed> {
1616
Widget build(BuildContext context) {
1717
return FutureProvider.value(
1818
value: _postService.getFeed(),
19-
child: Scaffold(body: ListPosts()),
19+
child: Scaffold(body: ListPosts(null)),
2020
);
2121
}
2222
}

frontend/lib/screens/main/posts/Item.dart

+10
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,16 @@ class _ItemPostState extends State<ItemPost> {
6161
Row(
6262
mainAxisAlignment: MainAxisAlignment.spaceAround,
6363
children: [
64+
Row(
65+
children: [
66+
IconButton(
67+
icon: new Icon(Icons.chat_bubble_outline,
68+
color: Colors.blue, size: 30.0),
69+
onPressed: () => Navigator.pushNamed(
70+
context, '/replies',
71+
arguments: widget.post)),
72+
],
73+
),
6474
Row(
6575
children: [
6676
IconButton(

frontend/lib/screens/main/posts/list.dart

+6-3
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@ import 'package:twitter/services/posts.dart';
77
import 'package:twitter/services/user.dart';
88

99
class ListPosts extends StatefulWidget {
10-
ListPosts({Key key}) : super(key: key);
10+
PostModel post;
11+
ListPosts(this.post, {Key key}) : super(key: key);
1112

1213
@override
1314
_ListPostsState createState() => _ListPostsState();
@@ -18,8 +19,10 @@ class _ListPostsState extends State<ListPosts> {
1819
PostService _postService = PostService();
1920
@override
2021
Widget build(BuildContext context) {
21-
final posts = Provider.of<List<PostModel>>(context) ?? [];
22-
22+
List<PostModel> posts = Provider.of<List<PostModel>>(context) ?? [];
23+
if (widget.post != null) {
24+
posts.insert(0, widget.post);
25+
}
2326
return ListView.builder(
2427
itemCount: posts.length,
2528
itemBuilder: (context, index) {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
import 'package:flutter/material.dart';
2+
import 'package:provider/provider.dart';
3+
import 'package:twitter/models/post.dart';
4+
import 'package:twitter/screens/main/posts/list.dart';
5+
import 'package:twitter/services/posts.dart';
6+
7+
class Replies extends StatefulWidget {
8+
Replies({Key key}) : super(key: key);
9+
10+
@override
11+
_RepliesState createState() => _RepliesState();
12+
}
13+
14+
class _RepliesState extends State<Replies> {
15+
PostService _postService = PostService();
16+
String text = '';
17+
TextEditingController _textController = TextEditingController();
18+
19+
@override
20+
Widget build(BuildContext context) {
21+
PostModel args = ModalRoute.of(context).settings.arguments;
22+
return FutureProvider.value(
23+
value: _postService.getReplies(args),
24+
child: Container(
25+
child: Scaffold(
26+
body: Container(
27+
child: Column(
28+
children: [
29+
Expanded(child: ListPosts(args)),
30+
Container(
31+
padding: EdgeInsets.symmetric(vertical: 10, horizontal: 10),
32+
child: Column(
33+
crossAxisAlignment: CrossAxisAlignment.end,
34+
children: [
35+
Form(
36+
child: TextFormField(
37+
controller: _textController,
38+
onChanged: (val) {
39+
setState(() {
40+
text = val;
41+
});
42+
},
43+
)),
44+
SizedBox(
45+
height: 10,
46+
),
47+
FlatButton(
48+
textColor: Colors.white,
49+
color: Colors.blue,
50+
onPressed: () async {
51+
await _postService.reply(args, text);
52+
_textController.text = '';
53+
setState(() {
54+
text = '';
55+
});
56+
},
57+
child: Text("Reply"))
58+
],
59+
),
60+
)
61+
],
62+
),
63+
),
64+
),
65+
));
66+
}
67+
}

frontend/lib/screens/main/profile/profile.dart

+1-1
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ class _ProfileState extends State<Profile> {
114114
]))
115115
];
116116
},
117-
body: ListPosts()),
117+
body: ListPosts(null)),
118118
)));
119119
}
120120
}

frontend/lib/screens/wrapper.dart

+3-1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import 'package:twitter/models/user.dart';
44
import 'package:twitter/screens/auth/signup.dart';
55
import 'package:twitter/screens/main/home.dart';
66
import 'package:twitter/screens/main/posts/add.dart';
7+
import 'package:twitter/screens/main/posts/replies.dart';
78
import 'package:twitter/screens/main/profile/edit.dart';
89
import 'package:twitter/screens/main/profile/profile.dart';
910

@@ -25,7 +26,8 @@ class Wrapper extends StatelessWidget {
2526
'/': (context) => Home(),
2627
'/add': (context) => Add(),
2728
'/profile': (context) => Profile(),
28-
'/edit': (context) => Edit()
29+
'/edit': (context) => Edit(),
30+
'/replies': (context) => Replies()
2931
});
3032
}
3133
}

frontend/lib/services/posts.dart

+25-1
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ class PostService {
1818
retweetsCount: doc.data()['retweetsCount'] ?? 0,
1919
retweet: doc.data()['retweet'] ?? false,
2020
originalId: doc.data()['originalId'] ?? null,
21+
ref: doc.reference,
2122
);
2223
}).toList();
2324
}
@@ -33,6 +34,7 @@ class PostService {
3334
retweetsCount: snapshot.data()['retweetsCount'] ?? 0,
3435
retweet: snapshot.data()['retweet'] ?? false,
3536
originalId: snapshot.data()['originalId'] ?? null,
37+
ref: snapshot.reference,
3638
)
3739
: null;
3840
}
@@ -41,7 +43,20 @@ class PostService {
4143
await FirebaseFirestore.instance.collection("posts").add({
4244
'text': text,
4345
'creator': FirebaseAuth.instance.currentUser.uid,
44-
'timestamp': FieldValue.serverTimestamp()
46+
'timestamp': FieldValue.serverTimestamp(),
47+
'retweet': false
48+
});
49+
}
50+
51+
Future reply(PostModel post, String text) async {
52+
if (text == '') {
53+
return;
54+
}
55+
await post.ref.collection("replies").add({
56+
'text': text,
57+
'creator': FirebaseAuth.instance.currentUser.uid,
58+
'timestamp': FieldValue.serverTimestamp(),
59+
'retweet': false
4560
});
4661
}
4762

@@ -149,6 +164,15 @@ class PostService {
149164
.map(_postListFromSnapshot);
150165
}
151166

167+
Future<List<PostModel>> getReplies(PostModel post) async {
168+
QuerySnapshot querySnapshot = await post.ref
169+
.collection("replies")
170+
.orderBy('timestamp', descending: true)
171+
.get();
172+
173+
return _postListFromSnapshot(querySnapshot);
174+
}
175+
152176
Future<List<PostModel>> getFeed() async {
153177
List<String> usersFollowing = await UserService() //['uid1', 'uid2']
154178
.getUserFollowing(FirebaseAuth.instance.currentUser.uid);

0 commit comments

Comments
 (0)