Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/add comment screen #13

Merged
merged 6 commits into from
Nov 27, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
74 changes: 74 additions & 0 deletions lib/adapters/comment_adapter.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import 'package:cached_network_image/cached_network_image.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/material.dart';
import 'package:news_expose_2k21/functions.dart';

class Comment extends StatefulWidget {
final String commentContent;
final Timestamp commentTimestamp;
final String userBio;
final String userImage;
final String userName;

const Comment(
{Key? key,
required this.commentContent,
required this.commentTimestamp,
required this.userBio,
required this.userImage,
required this.userName})
: super(key: key);

factory Comment.fromDocument(final documentSnapshot) => Comment(
commentContent: documentSnapshot['comment_content'],
commentTimestamp: documentSnapshot['comment_timestamp'],
userBio: documentSnapshot['user_bio'],
userImage: documentSnapshot['user_image'],
userName: documentSnapshot['user_name'],
);

@override
State<Comment> createState() => _CommentState();
}

class _CommentState extends State<Comment> {
late final String _commentContent = widget.commentContent;
late final Timestamp _commentTimestamp = widget.commentTimestamp;
late final String _userBio = widget.userBio;
late final String _userImage = widget.userImage;
late final String _userName = widget.userName;

@override
Widget build(BuildContext context) => ListTile(
leading: _userImage.isNotEmpty
? CircleAvatar(
radius: 23.0,
backgroundImage: CachedNetworkImageProvider(_userImage),
backgroundColor: colorEerieBlack,
)
: CircleAvatar(
child: Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(22.0),
gradient: linearProfile,
),
),
),
title: Column(
children: <Widget>[
Container(
alignment: Alignment.topLeft,
child: initTitle2(_userBio,
size: 17.0, fontWeight: FontWeight.bold, fontFamily: ''),
),
Container(
alignment: Alignment.topLeft,
child: initTitle2(
'${initTimestamp(_commentTimestamp)} · $_userName'),
),
],
),
subtitle: Container(
alignment: Alignment.topLeft, child: initTitle2(_commentContent)),
);
}
68 changes: 37 additions & 31 deletions lib/adapters/update_adapter.dart
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ class Update extends StatefulWidget {
updateContent: documentSnapshot['update_content'],
updateTimestamp: documentSnapshot['update_timestamp'],
userId: documentSnapshot['user_id'],
seen: documentSnapshot['Seen'],
seen: documentSnapshot['seen'],
);

seenCount(final seen) {
Expand Down Expand Up @@ -71,12 +71,16 @@ class _UpdateState extends State<Update> {
}

final user = User.fromDocument(dataSnapshot.data);

final userBio = user.userBio!;
final userImage = user.userImage!;
final userName = user.userName!;

return ListTile(
leading: user.userImage!.isNotEmpty
leading: userImage.isNotEmpty
? CircleAvatar(
radius: 25.0,
backgroundImage:
CachedNetworkImageProvider(user.userImage!),
backgroundImage: CachedNetworkImageProvider(userImage),
backgroundColor: colorEerieBlack,
)
: CircleAvatar(
Expand All @@ -87,10 +91,10 @@ class _UpdateState extends State<Update> {
),
),
),
title: initTitle2(user.userBio,
title: initTitle2(userBio,
size: 17.0, fontWeight: FontWeight.bold, fontFamily: ''),
subtitle: initTitle2(
'${initUpdateTimestamp(_updateTimestamp)} · ${user.userName}'),
subtitle:
initTitle2('${initTimestamp(_updateTimestamp)} · $userName'),
);
},
),
Expand Down Expand Up @@ -160,18 +164,20 @@ class _UpdateState extends State<Update> {
);

_onSeen() {
updatesRef.doc(_updateId).update({'Seen.$userId': !_isSeen});
updatesRef.doc(_updateId).update({'seen.$userId': !_isSeen});

setState(() {
_seenCount += _isSeen ? -1 : 1;
_isSeen = !_isSeen;
});
}

_onComment(final context, final updateId) =>
Navigator.push(context, MaterialPageRoute(builder: (context) => CommentScreen(
updateId: updateId,
)));
_onComment(final context, final updateId) => Navigator.push(
context,
MaterialPageRoute(
builder: (context) => CommentScreen(
updateId: updateId,
)));

@override
void initState() {
Expand All @@ -181,24 +187,24 @@ class _UpdateState extends State<Update> {

@override
Widget build(BuildContext context) => Container(
margin: const EdgeInsets.all(18.0),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(25.0),
color: colorEerieBlack,
),
child: Column(
children: <Widget>[
_initHead(),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 18.0),
child: Column(
children: <Widget>[
_initBody(),
_initFoot(context),
],
margin: const EdgeInsets.all(18.0),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(25.0),
color: colorEerieBlack,
),
child: Column(
children: <Widget>[
_initHead(),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 18.0),
child: Column(
children: <Widget>[
_initBody(),
_initFoot(context),
],
),
),
),
],
),
);
],
),
);
}
192 changes: 190 additions & 2 deletions lib/comment_screen.dart
Original file line number Diff line number Diff line change
@@ -1,4 +1,11 @@
import 'package:cached_network_image/cached_network_image.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:news_expose_2k21/adapters/comment_adapter.dart';
import 'package:news_expose_2k21/functions.dart';
import 'package:news_expose_2k21/models/user_model.dart';

class CommentScreen extends StatefulWidget {
final String updateId;
Expand All @@ -10,8 +17,189 @@ class CommentScreen extends StatefulWidget {
}

class _CommentScreenState extends State<CommentScreen> {
late final String _updateId = widget.updateId;
final _commentContentController = TextEditingController();
bool _isLoading = false;
List<Comment> _comments = [];

_initAppBar() => AppBar(
systemOverlayStyle: SystemUiOverlayStyle.light,
backgroundColor: colorChineseBlack,
toolbarHeight: 55.0,
flexibleSpace: SafeArea(
child: Container(
decoration: const BoxDecoration(
gradient: linearAppBar,
),
child: Container(
alignment: Alignment.centerLeft,
margin: const EdgeInsets.only(left: 60.0),
child: initTitle2('Comments', size: 23.0),
),
),
),
);

_onComment(final context, final userBio, final userImage, final userName,
final commentContent) {
onFocusLost(context);

if (commentContent.isEmpty) {
buildFlutterToast('Comment cannot be empty!', colorKUCrimson);
} else {
addComment() =>
updatesRef.doc(_updateId).collection('Comments').doc().set({
'comment_content': commentContent,
'comment_timestamp': Timestamp.now(),
'user_bio': userBio,
'user_image': userImage,
'user_name': userName,
});

addComment().then((value) {
setState(() {
_commentContentController.clear();
_onLoadComments();
});
});
}
}

_loadComments() => _isLoading
? buildCircularProgress()
: SingleChildScrollView(
physics: const BouncingScrollPhysics(),
child: Column(
children: _comments,
),
);

_onLoadComments() async {
setState(() {
_isLoading = true;
});

final querySnapshot =
await updatesRef.doc(_updateId).collection('Comments').get();

setState(() {
_isLoading = false;
_comments = querySnapshot.docs
.map((documentSnapshot) => Comment.fromDocument(documentSnapshot))
.toList();
});
}

@override
Widget build(BuildContext context) {
return Container();
void initState() {
super.initState();
_onLoadComments();
}

@override
Widget build(BuildContext context) => GestureDetector(
onTap: () => onFocusLost(context),
child: Scaffold(
appBar: _initAppBar(),
body: Stack(
children: <Widget>[
Container(
decoration: const BoxDecoration(
image: DecorationImage(
image: AssetImage('res/images/img_background_2.png'),
fit: BoxFit.cover,
),
),
),
Column(
children: <Widget>[
Expanded(
child: _loadComments(),
),
Container(
alignment: Alignment.bottomCenter,
height: 55.0,
decoration: const BoxDecoration(
gradient: linearAppBar,
),
child: Row(
children: <Widget>[
Expanded(
child: FutureBuilder(
future: usersRef.doc(userId).get(),
builder: (context, dataSnapshot) {
if (!dataSnapshot.hasData) {
return buildCircularProgress();
}

final user = User.fromDocument(dataSnapshot.data);

final userBio = user.userBio!;
final userImage = user.userImage!;
final userName = user.userName!;

return ListTile(
leading: userImage.isNotEmpty
? CircleAvatar(
radius: 20.0,
backgroundImage:
CachedNetworkImageProvider(
userImage),
backgroundColor: colorEerieBlack,
)
: CircleAvatar(
child: Container(
decoration: BoxDecoration(
borderRadius:
BorderRadius.circular(22.0),
gradient: linearProfile,
),
),
),

title: TextField(
controller: _commentContentController,
inputFormatters: [
LengthLimitingTextInputFormatter(1024),
],
style: const TextStyle(color: colorFulvous),
decoration: const InputDecoration(
border: InputBorder.none,
hintText: 'Add a comment...',
hintStyle: TextStyle(
fontFamily: 'Tahoma',
fontSize: 15.0,
color: colorBrightGray,
),
),
textInputAction: TextInputAction.done,
),

trailing: GestureDetector(
onTap: () => _onComment(
context,
userBio,
userImage,
userName,
_commentContentController.text.trim()),
child: SvgPicture.string(
createSendUIButton,
allowDrawingOutsideViewBox: true,
),
),

//
);
},
),
),
],
),
),
],
),
],
),
),
);
}
Loading