From 02b8534750bf9c40cbcd572da4a8ca4a96532645 Mon Sep 17 00:00:00 2001 From: Erick Date: Wed, 28 Aug 2024 15:27:22 +0300 Subject: [PATCH] feat: chirp homepage design done --- .../chirp/controllers/chirp_controller.dart | 36 +---- .../chirp/models/services/post_service.dart | 28 +++- lib/tools/chirp/pages/chirp_home_page.dart | 45 ++++-- lib/tools/chirp/pages/feed_page.dart | 153 ++++++++++-------- lib/tools/chirp/pages/post_create_page.dart | 15 -- 5 files changed, 156 insertions(+), 121 deletions(-) diff --git a/lib/tools/chirp/controllers/chirp_controller.dart b/lib/tools/chirp/controllers/chirp_controller.dart index 4ab9089..6d2b65b 100644 --- a/lib/tools/chirp/controllers/chirp_controller.dart +++ b/lib/tools/chirp/controllers/chirp_controller.dart @@ -5,45 +5,19 @@ import 'package:dartz/dartz.dart'; class ChirpController extends GetxController { final PostService _service = PostService(); UserController userController = Get.find(); - RxList posts = RxList(); - RxInt currentPage = 0.obs; - RxBool feedLoading = false.obs; - RxBool myPostsLoading = false.obs; - RxBool upvotedPostsLoading = false.obs; - - @override - void onInit() { - super.onInit(); - debugPrint("Chirp Controller Loaded"); - } - - Future>> fetchPosts({ - bool nextPage = false, - previousPage = false, - }) async { - feedLoading.value = true; - - int page = 1; + // Loading posts comments - if (nextPage) { - page = currentPage.value; - } else if (previousPage && currentPage > 1) { - page = currentPage.value -= 1; - } - final result = - await _service.fetchPosts(userController.authHeaders, page: page); - feedLoading.value = false; + Future>> fetchUserPosts() async { + final result = await _service.fetchUserPosts( + userController.authHeaders, userController.user.value!.id!); return result.fold((l) { return left(l); }, (r) { - posts.value = r["posts"]; - currentPage.value = r["nextPage"]; - return right(posts); + return right(r); }); } - // Loading posts comments Future>> fetchPostComments(Post post) async { final result = await _service.fetchPostComments(userController.authHeaders, post.id); diff --git a/lib/tools/chirp/models/services/post_service.dart b/lib/tools/chirp/models/services/post_service.dart index 3c7b0d6..3b47da3 100644 --- a/lib/tools/chirp/models/services/post_service.dart +++ b/lib/tools/chirp/models/services/post_service.dart @@ -11,7 +11,7 @@ class PostService with ChirpService { }) async { try { final response = await http.get( - Uri.parse("${ChirpService.urlPrefix}/posts/all?pages=$page"), + Uri.parse("${ChirpService.urlPrefix}/posts/all?page=$page"), headers: authHeaders, ); @@ -71,6 +71,32 @@ class PostService with ChirpService { } } + Future>> fetchUserPosts( + Map authHeaders, String userID) async { + try { + final response = await http.get( + Uri.parse("${ChirpService.urlPrefix}/posts/user/$userID"), + headers: authHeaders, + ); + if (response.statusCode == 200) { + final List> rawData = + json.decode(response.body).cast>(); + + final List comments = + rawData.map((e) => Post.fromJson(e)).toList().cast(); + + return right(comments); + } + return left( + json.decode(response.body)["error"], + ); + } catch (e) { + return left( + "Encountered an error we did, check your connection you must, ${e.toString()}", + ); + } + } + Future>> fetchPostComments( Map authHeaders, String post, { diff --git a/lib/tools/chirp/pages/chirp_home_page.dart b/lib/tools/chirp/pages/chirp_home_page.dart index c9cad54..841db70 100644 --- a/lib/tools/chirp/pages/chirp_home_page.dart +++ b/lib/tools/chirp/pages/chirp_home_page.dart @@ -20,9 +20,6 @@ class _ChirpHomePageState extends State { @override void initState() { super.initState(); - controller.fetchPosts().then((value) { - value.fold((l) {}, (r) {}); - }); } @override @@ -30,7 +27,7 @@ class _ChirpHomePageState extends State { return Scaffold( backgroundColor: Theme.of(context).colorScheme.surfaceDim, body: DefaultTabController( - length: 3, + length: 2, child: CustomScrollView( slivers: [ SliverAppBar( @@ -77,9 +74,8 @@ class _ChirpHomePageState extends State { snap: true, bottom: const TabBar( tabs: [ - Tab(text: 'Feed'), + Tab(text: 'My Feed'), Tab(text: "My Posts"), - Tab(text: "Upvoted"), ], ), ), @@ -92,11 +88,40 @@ class _ChirpHomePageState extends State { ), ), SliverFillRemaining( + hasScrollBody: true, + fillOverscroll: true, child: TabBarView(children: [ - FeedPage(), - Text("Holla"), - Text("Moma"), - ])), + const FeedPage(), + FutureBuilder( + future: controller.fetchUserPosts(), + builder: (context, snapshot) { + if (snapshot.connectionState != ConnectionState.done) { + return ListView.separated( + itemBuilder: (context, index) { + return const EmptyPostCard(); + }, + separatorBuilder: (context, index) => + const SizedBox( + height: 4, + ), + itemCount: 12); + } + return snapshot.data!.fold((l) { + return Center( + child: Text("Snap! $l"), + ); + }, (r) { + return ListView.separated( + itemBuilder: (context, index) { + final post = r[index]; + return PostCard(post: post); + }, + separatorBuilder: (context, index) => + const SizedBox(height: 2), + itemCount: r.length); + }); + }), + ])), ], ), ), diff --git a/lib/tools/chirp/pages/feed_page.dart b/lib/tools/chirp/pages/feed_page.dart index 5b9dec6..e2ea6a5 100644 --- a/lib/tools/chirp/pages/feed_page.dart +++ b/lib/tools/chirp/pages/feed_page.dart @@ -1,8 +1,6 @@ -import 'package:flutter/material.dart'; +import 'package:academia/exports/barrel.dart'; import 'package:get/get.dart'; -import 'package:lottie/lottie.dart'; import '../widgets/widgets.dart'; -import '../controllers/chirp_controller.dart'; class FeedPage extends StatefulWidget { const FeedPage({super.key}); @@ -12,68 +10,95 @@ class FeedPage extends StatefulWidget { } class _FeedPageState extends State { - final ChirpController controller = Get.find(); + bool pageLoading = true; + bool morePostsLoading = false; + List feedPosts = []; + int nextPage = 1; + bool hasMorePages = true; + + final UserController userController = Get.find(); + final PostService _service = PostService(); + @override + void initState() { + super.initState(); + _service.fetchPosts(userController.authHeaders).then((value) { + value.fold((l) { + debugPrint(l); + }, (r) { + feedPosts.addAll(r["posts"]); + if (nextPage == r["nextPage"]) { + setState(() { + hasMorePages = false; + }); + return; + } + + nextPage = r["nextPage"]; + setState(() {}); + }); + }); + setState(() { + pageLoading = false; + }); + } + @override Widget build(BuildContext context) { - return RefreshIndicator( - child: Obx( - () => controller.feedLoading.value || true - ? ListView.builder( - itemBuilder: (context, index) => EmptyPostCard(), - ) - : Text("Loaded"), - ), - onRefresh: () async { - Future.delayed(Duration(seconds: 5)); - }); + return pageLoading + ? ListView.separated( + itemBuilder: (context, index) { + return const EmptyPostCard(); + }, + separatorBuilder: (context, index) => const SizedBox( + height: 4, + ), + itemCount: 12) + : feedPosts.isEmpty + ? const Center( + child: Text("No posts here yet"), + ) + : ListView.separated( + itemBuilder: (context, index) { + if (index < feedPosts.length) { + final post = feedPosts[index]; + return PostCard(post: post); + } + return hasMorePages + ? morePostsLoading + ? const LinearProgressIndicator() + : TextButton( + onPressed: fetchMorePosts, + child: const Text("Load more"), + ) + : const Text("You have reached the end of feed!"); + }, + separatorBuilder: (context, index) => const SizedBox(height: 2), + itemCount: feedPosts.length + 1); + } + + Future fetchMorePosts() async { + setState(() { + morePostsLoading = true; + }); + + _service + .fetchPosts(userController.authHeaders, page: nextPage) + .then((value) { + value.fold((l) { + debugPrint(l); + }, (r) { + feedPosts.addAll(r["posts"]); + setState(() {}); + if (nextPage == r["nextPage"]) { + hasMorePages = false; + return; + } + nextPage = r["nextPage"]; + }); + }); + + setState(() { + morePostsLoading = false; + }); } } -// Obx( -// () => controller.isLoading.value -// ? SingleChildScrollView( -// child: Column( -// children: [ -// Lottie.asset("assets/lotties/fetching.json"), -// const SizedBox(height: 22), -// Text( -// "Fetching posts", -// textAlign: TextAlign.center, -// style: Theme.of(context).textTheme.headlineSmall, -// ), -// ], -// ), -// ) -// : RefreshIndicator( -// onRefresh: () async { -// await controller.fetchPosts(); -// }, -// child: controller.posts.isEmpty -// ? SingleChildScrollView( -// child: Column( -// children: [ -// Lottie.asset("assets/lotties/empty.json"), -// Text( -// "Argh snap! We couldn't find posts at the moment. Please try again later", -// textAlign: TextAlign.center, -// style: Theme.of(context) -// .textTheme -// .headlineSmall, -// ), -// ], -// ), -// ) -// : ListView.separated( -// itemBuilder: (context, index) { -// final data = controller.posts[index]; -// return PostCard(post: data); -// }, -// separatorBuilder: (context, index) => -// const SizedBox( -// height: 8, -// child: Divider(thickness: 0.3), -// ), -// itemCount: controller.posts.length, -// ), -// ), -// ), -// diff --git a/lib/tools/chirp/pages/post_create_page.dart b/lib/tools/chirp/pages/post_create_page.dart index 0f815da..dc18b4c 100644 --- a/lib/tools/chirp/pages/post_create_page.dart +++ b/lib/tools/chirp/pages/post_create_page.dart @@ -27,21 +27,6 @@ class _PostCreatePageState extends State { }, icon: const Icon(Ionicons.close), ), - // actions: [ - // IconButton( - // onPressed: () { - // Navigator.of(context).push(MaterialPageRoute( - // builder: (context) => ImageConfigScreen( - // onImagePicked: (file) { - // setState(() { - // imageFiles.add(file!); - // }); - // }, - // ))); - // }, - // icon: const Icon(Ionicons.attach_outline), - // ), - // ], ), body: SafeArea( minimum: const EdgeInsets.all(12),