From c4157c3e2393a9a895b9454b47f18a92c861f139 Mon Sep 17 00:00:00 2001 From: LittleSheep Date: Sun, 24 Mar 2024 12:12:13 +0800 Subject: [PATCH] :sparkles: Comment view --- lib/screens/explore.dart | 10 ++-- lib/widgets/feed.dart | 29 ++++++++++ lib/widgets/posts/comments.dart | 98 +++++++++++++++++++++++++++++++++ 3 files changed, 132 insertions(+), 5 deletions(-) create mode 100644 lib/widgets/posts/comments.dart diff --git a/lib/screens/explore.dart b/lib/screens/explore.dart index 631c561..5be6ca9 100644 --- a/lib/screens/explore.dart +++ b/lib/screens/explore.dart @@ -48,13 +48,13 @@ class _ExploreScreenState extends State { final result = PaginationResult.fromJson(jsonDecode(utf8.decode(res.bodyBytes))); final isLastPage = (result.count - pageKey) < pageSize; + final items = + result.data?.map((x) => Feed.fromJson(x)).toList() ?? List.empty(); if (isLastPage || result.data == null) { - paginationController.appendLastPage(feed); + paginationController.appendLastPage(items); } else { - final feed = - result.data?.map((x) => Feed.fromJson(x)).toList() ?? List.empty(); - final nextPageKey = pageKey + feed.length; - paginationController.appendPage(feed, nextPageKey); + final nextPageKey = pageKey + items.length; + paginationController.appendPage(items, nextPageKey); } } else { paginationController.error = utf8.decode(res.bodyBytes); diff --git a/lib/widgets/feed.dart b/lib/widgets/feed.dart index 474e8d2..64f7b4b 100644 --- a/lib/widgets/feed.dart +++ b/lib/widgets/feed.dart @@ -3,12 +3,21 @@ import 'package:flutter_carousel_widget/flutter_carousel_widget.dart'; import 'package:flutter_markdown/flutter_markdown.dart'; import 'package:solaragent/models/feed.dart'; import 'package:solaragent/widgets/image.dart'; +import 'package:solaragent/widgets/posts/comments.dart'; class FeedItem extends StatelessWidget { final Feed item; const FeedItem({super.key, required this.item}); + void viewComments(BuildContext context) { + showModalBottomSheet( + context: context, + isScrollControlled: true, + builder: (context) => CommentListWidget(parent: item), + ); + } + bool hasAttachments() => item.attachments != null && item.attachments!.isNotEmpty; @@ -22,6 +31,7 @@ class FeedItem extends StatelessWidget { Widget build(BuildContext context) { return Column( children: [ + // Author info Container( color: Colors.grey[50], child: ListTile( @@ -37,11 +47,13 @@ class FeedItem extends StatelessWidget { ), ), ), + // Content Markdown( data: item.content, shrinkWrap: true, physics: const NeverScrollableScrollPhysics(), ), + // Attachments view hasAttachments() ? Container( decoration: const BoxDecoration( @@ -81,6 +93,23 @@ class FeedItem extends StatelessWidget { ), ) : Container(), + // Actions + Container( + padding: const EdgeInsets.symmetric(horizontal: 8), + decoration: const BoxDecoration( + border: + Border(top: BorderSide(width: 0.3, color: Color(0xffdedede))), + ), + child: Row( + children: [ + TextButton.icon( + icon: const Icon(Icons.comment), + label: Text(item.commentCount.toString()), + onPressed: () => viewComments(context), + ) + ], + ), + ), ], ); } diff --git a/lib/widgets/posts/comments.dart b/lib/widgets/posts/comments.dart new file mode 100644 index 0000000..76ad099 --- /dev/null +++ b/lib/widgets/posts/comments.dart @@ -0,0 +1,98 @@ +import 'dart:convert'; + +import 'package:flutter/material.dart'; +import 'package:http/http.dart'; +import 'package:infinite_scroll_pagination/infinite_scroll_pagination.dart'; +import 'package:solaragent/models/feed.dart'; +import 'package:solaragent/models/pagination.dart'; +import 'package:solaragent/widgets/feed.dart'; + +class CommentListWidget extends StatefulWidget { + final Feed parent; + + const CommentListWidget({super.key, required this.parent}); + + @override + State createState() => _CommentListWidgetState(); +} + +class _CommentListWidgetState extends State { + static const pageSize = 5; + + final client = Client(); + + final PagingController paginationController = + PagingController(firstPageKey: 0); + + List feed = List.empty(); + + @override + void initState() { + super.initState(); + paginationController.addPageRequestListener((pageKey) { + pullFeed(pageKey); + }); + } + + Future pullFeed(int pageKey) async { + var offset = pageKey; + var take = pageSize; + + var dataset = "${widget.parent.modelType}s"; + var alias = widget.parent.alias; + + var uri = Uri.parse( + 'https://co.solsynth.dev/api/p/$dataset/$alias/comments?take=$take&offset=$offset', + ); + + var res = await client.get(uri); + if (res.statusCode == 200) { + final result = + PaginationResult.fromJson(jsonDecode(utf8.decode(res.bodyBytes))); + final isLastPage = (result.count - pageKey) < pageSize; + final items = + result.data?.map((x) => Feed.fromJson(x)).toList() ?? List.empty(); + if (isLastPage || result.data == null) { + paginationController.appendLastPage(items); + } else { + final nextPageKey = pageKey + items.length; + paginationController.appendPage(items, nextPageKey); + } + } else { + paginationController.error = utf8.decode(res.bodyBytes); + } + } + + @override + Widget build(BuildContext context) { + return Column( + children: [ + Container( + padding: const EdgeInsets.only(left: 10, right: 10, top: 20), + child: ListTile( + title: Text( + 'Comments', + style: Theme.of(context).textTheme.headlineSmall, + ), + ), + ), + Expanded( + child: PagedListView( + pagingController: paginationController, + builderDelegate: PagedChildBuilderDelegate( + itemBuilder: (context, item, index) => FeedItem( + item: item, + ), + ), + ), + ), + ], + ); + } + + @override + void dispose() { + paginationController.dispose(); + super.dispose(); + } +}