Skip to content

Commit

Permalink
Merge pull request #143 from ProximaEPFL/post-page
Browse files Browse the repository at this point in the history
Post page UI foundation
  • Loading branch information
CHOOSEIT authored Apr 26, 2024
2 parents 5f355f7 + 23369bb commit bbe1f58
Show file tree
Hide file tree
Showing 15 changed files with 638 additions and 8 deletions.
29 changes: 29 additions & 0 deletions lib/models/ui/comment_post.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import "package:flutter/foundation.dart";

@immutable
class CommentPost {
final String content;
final String ownerDisplayName;

const CommentPost({
required this.content,
required this.ownerDisplayName,
});

@override
bool operator ==(Object other) {
if (identical(this, other)) return true;

return other is CommentPost &&
other.content == content &&
other.ownerDisplayName == ownerDisplayName;
}

@override
int get hashCode {
return Object.hash(
content,
ownerDisplayName,
);
}
}
7 changes: 7 additions & 0 deletions lib/viewmodels/post_view_model.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import "package:hooks_riverpod/hooks_riverpod.dart";
import "package:proxima/models/ui/comment_post.dart";

// This provider is used to store the list of comments that are displayed in the post page.
final commentListProvider = Provider<List<CommentPost>>((ref) {
return List.empty();
});
13 changes: 8 additions & 5 deletions lib/views/home_content/feed/post_card/post_card.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import "package:proxima/models/ui/post_overview.dart";
import "package:proxima/views/home_content/feed/post_card/comment_widget.dart";
import "package:proxima/views/home_content/feed/post_card/user_bar_widget.dart";
import "package:proxima/views/home_content/feed/post_card/votes_widget.dart";
import "package:proxima/views/navigation/routes.dart";

/// This widget is used to display the post card in the home feed.
/// It contains the post title, description, votes, comments
Expand All @@ -23,6 +24,10 @@ class PostCard extends StatelessWidget {
required this.postOverview,
});

void _onPostSelect(BuildContext context, PostOverview post) {
Navigator.pushNamed(context, Routes.post.name, arguments: post);
}

@override
Widget build(BuildContext context) {
final postBody = ListTile(
Expand Down Expand Up @@ -53,8 +58,7 @@ class PostCard extends StatelessWidget {
customBorder: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(20),
),
//TODO: Implement the logic to navigate to the post
onTap: () => {},
onTap: () => _onPostSelect(context, postOverview),
child: CommentWidget(
key: postCardCommentsKey,
commentNumber: postOverview.commentNumber,
Expand All @@ -69,13 +73,12 @@ class PostCard extends StatelessWidget {
key: postCardKey,
clipBehavior: Clip.hardEdge,
child: InkWell(
//TODO: Implement the logic to navigate to the post
onTap: () => {},
onTap: () => _onPostSelect(context, postOverview),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Padding(
padding: const EdgeInsets.only(left: 16, right: 0.8, top: 8),
padding: const EdgeInsets.only(left: 16, top: 8),
child: UserBarWidget(
key: postCardUserKey,
posterUsername: postOverview.ownerDisplayName,
Expand Down
7 changes: 6 additions & 1 deletion lib/views/home_content/feed/post_card/user_bar_widget.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ import "package:flutter/material.dart";
/// This widget is used to display the user bar in the post card.
/// It contains the user's profile picture and username.
class UserBarWidget extends StatelessWidget {
static const displayNameTextKey = Key("displayNameText");

const UserBarWidget({
super.key,
required this.posterUsername,
Expand All @@ -21,7 +23,10 @@ class UserBarWidget extends StatelessWidget {
),
Padding(
padding: const EdgeInsets.only(left: 8),
child: Text(posterUsername),
child: Text(
key: displayNameTextKey,
posterUsername,
),
),
],
);
Expand Down
2 changes: 1 addition & 1 deletion lib/views/home_content/feed/post_card/votes_widget.dart
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ class VotesWidget extends HookConsumerWidget {
child: Padding(
padding: const EdgeInsets.all(3),
child: Row(
mainAxisAlignment: MainAxisAlignment.end,
mainAxisAlignment: MainAxisAlignment.start,
children: [
upvote,
downvote,
Expand Down
13 changes: 12 additions & 1 deletion lib/views/navigation/routes.dart
Original file line number Diff line number Diff line change
@@ -1,16 +1,19 @@
import "package:flutter/material.dart";
import "package:proxima/models/ui/post_overview.dart";
import "package:proxima/views/pages/create_account_page.dart";
import "package:proxima/views/pages/home/home_page.dart";
import "package:proxima/views/pages/login/login_page.dart";
import "package:proxima/views/pages/new_post/new_post_page.dart";
import "package:proxima/views/pages/post/post_page.dart";
import "package:proxima/views/pages/profile/profile_page.dart";

enum Routes {
home("home"),
login("login"),
profile("profile"),
newPost("new post"),
createAccount("createAccount");
createAccount("createAccount"),
post("post");

final String name;

Expand All @@ -32,6 +35,14 @@ enum Routes {
return const NewPostPage();
case createAccount:
return const CreateAccountPage();
case post:
if (args is PostOverview) {
return PostPage(
postOverview: args,
);
} else {
throw Exception("PostOverview object required");
}
}
}
}
Expand Down
83 changes: 83 additions & 0 deletions lib/views/pages/post/post_page.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
import "package:flutter/material.dart";
import "package:hooks_riverpod/hooks_riverpod.dart";
import "package:proxima/models/ui/post_overview.dart";
import "package:proxima/viewmodels/post_view_model.dart";
import "package:proxima/views/navigation/leading_back_button/leading_back_button.dart";
import "package:proxima/views/pages/post/post_page_widget/bottom_bar_add_comment.dart";
import "package:proxima/views/pages/post/post_page_widget/comment_list.dart";
import "package:proxima/views/pages/post/post_page_widget/complete_post_widget.dart";

class PostPage extends HookConsumerWidget {
static const postDistanceKey = Key("postDistance");
static const completePostWidgetKey = Key("completePostWidget");
static const commentListWidgetKey = Key("commentListWidget");
static const bottomBarAddCommentKey = Key("bottomBarAddComment");

static const _appBarTitle = "Post";

const PostPage({
super.key,
required this.postOverview,
});

final PostOverview postOverview;

@override
Widget build(BuildContext context, WidgetRef ref) {
ThemeData themeData = Theme.of(context);

final comments = ref.watch(commentListProvider);

List<Widget> appBarContent = [
const Text(_appBarTitle),
Text(
key: postDistanceKey,
//TODO: Add distance to post
"50m away",
style: themeData.textTheme.titleSmall,
),
];

List<Widget> bodyChildren = [
CompletePostWidget(
key: completePostWidgetKey,
post: postOverview,
),
const SizedBox(height: 10),
CommentList(
key: commentListWidgetKey,
comments: comments,
),
];

return Scaffold(
appBar: AppBar(
leading: const LeadingBackButton(),
title: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: appBarContent,
),
),
body: Padding(
padding: const EdgeInsets.only(top: 8, bottom: 8, left: 8, right: 8),
child: Center(
child: ListView(
children: bodyChildren,
),
),
),
persistentFooterButtons: [
Padding(
padding:
// This is necessary to prevent the keyboard from covering the bottom bar
EdgeInsets.only(bottom: MediaQuery.of(context).viewInsets.bottom),
child: const BottomBarAddComment(
key: bottomBarAddCommentKey,
//TODO: Replace with actual username
currentDisplayName: "Username",
),
),
],
);
}
}
58 changes: 58 additions & 0 deletions lib/views/pages/post/post_page_widget/bottom_bar_add_comment.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import "package:flutter/material.dart";

class BottomBarAddComment extends StatelessWidget {
static const commentUserAvatarKey = Key("commentUserAvatar");
static const addCommentTextFieldKey = Key("addCommentTextField");
static const postCommentButtonKey = Key("postCommentButton");

static const _textFieldHintAddComment = "Add a comment";

final String currentDisplayName;

const BottomBarAddComment({
super.key,
required this.currentDisplayName,
});

@override
Widget build(BuildContext context) {
return Row(
// Align items to the start of the cross axis
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Padding(
padding: const EdgeInsets.only(right: 8),
child: CircleAvatar(
key: commentUserAvatarKey,
radius: 22,
child: Text(currentDisplayName.substring(0, 1)),
),
),
const Expanded(
child: TextField(
key: addCommentTextFieldKey,
minLines: 1,
maxLines: 5,
decoration: InputDecoration(
contentPadding: EdgeInsets.all(8),
border: OutlineInputBorder(),
hintText: _textFieldHintAddComment,
),
),
),
Align(
// Keeps the IconButton centered in the cross axis
alignment: Alignment.center,
child: IconButton(
key: postCommentButtonKey,
icon: const Icon(Icons.send),
onPressed: () {
//TODO: handle add comment
FocusManager.instance.primaryFocus?.unfocus();
},
),
),
],
);
}
}
25 changes: 25 additions & 0 deletions lib/views/pages/post/post_page_widget/comment_list.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import "package:flutter/material.dart";
import "package:proxima/models/ui/comment_post.dart";
import "package:proxima/views/pages/post/post_page_widget/comment_post_widget.dart";

class CommentList extends StatelessWidget {
const CommentList({
super.key,
required this.comments,
});

final List<CommentPost> comments;

@override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.only(left: 16, right: 16),
child: Wrap(
runSpacing: 15,
children: comments
.map((comment) => CommentPostWidget(commentPost: comment))
.toList(),
),
);
}
}
38 changes: 38 additions & 0 deletions lib/views/pages/post/post_page_widget/comment_post_widget.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import "package:flutter/material.dart";
import "package:proxima/models/ui/comment_post.dart";

import "package:proxima/views/home_content/feed/post_card/user_bar_widget.dart";

class CommentPostWidget extends StatelessWidget {
static const commentWidgetKey = Key("commentWidget");
static const commentUserWidgetKey = Key("commentUserWidget");
static const commentContentKey = Key("commentContent");

final CommentPost commentPost;

const CommentPostWidget({
super.key,
required this.commentPost,
});

@override
Widget build(BuildContext context) {
return Column(
key: commentWidgetKey,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
UserBarWidget(
key: commentUserWidgetKey,
posterUsername: commentPost.ownerDisplayName,
),
Padding(
padding: const EdgeInsets.only(left: 32, top: 8),
child: Text(
key: commentContentKey,
commentPost.content,
),
),
],
);
}
}
Loading

0 comments on commit bbe1f58

Please sign in to comment.