import 'package:flutter/material.dart'; 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'; import 'package:solaragent/widgets/posts/reactions.dart'; class FeedItem extends StatefulWidget { final Feed item; const FeedItem({super.key, required this.item}); @override State createState() => _FeedItemState(); } class _FeedItemState extends State { int reactionCount = 0; Map? reactionList; void viewComments(BuildContext context) { showModalBottomSheet( context: context, isScrollControlled: true, builder: (context) => CommentList(parent: widget.item), ); } void viewReactions(BuildContext context) { showModalBottomSheet( context: context, builder: (context) => ReactionList( parent: widget.item, onReact: (symbol, num) { setState(() { if (!reactionList!.containsKey(symbol)) { reactionList![symbol] = 0; } reactionCount += num; reactionList![symbol] += num; }); }, ), ); } bool hasAttachments() => widget.item.attachments != null && widget.item.attachments!.isNotEmpty; String getDescription(String desc) => desc.isEmpty ? "No description yet." : desc; String getFileUrl(String fileId) => 'https://co.solsynth.dev/api/attachments/o/$fileId'; @override void initState() { reactionCount = widget.item.reactionCount; reactionList = widget.item.reactionList ?? {}; super.initState(); } @override Widget build(BuildContext context) { return Column( children: [ // Author info Container( color: Colors.grey[50], child: ListTile( title: Text(widget.item.author.name), leading: CircleAvatar( backgroundImage: NetworkImage(widget.item.author.avatar), ), subtitle: Text( getDescription(widget.item.author.description), overflow: TextOverflow.ellipsis, maxLines: 1, softWrap: false, ), ), ), // Content Markdown( data: widget.item.content, shrinkWrap: true, physics: const NeverScrollableScrollPhysics(), ), // Attachments view hasAttachments() ? Container( decoration: const BoxDecoration( border: Border( top: BorderSide(width: 0.3, color: Color(0xffdedede))), ), child: FlutterCarousel( options: CarouselOptions( height: 240.0, viewportFraction: 1.0, showIndicator: true, slideIndicator: const CircularSlideIndicator(), ), items: widget.item.attachments?.map((x) { return Builder( builder: (BuildContext context) { return SizedBox( width: MediaQuery.of(context).size.width, child: InkWell( child: Image.network( getFileUrl(x.fileId), fit: BoxFit.cover, ), onTap: () { Navigator.push(context, MaterialPageRoute(builder: (_) { return ImageLightbox( url: getFileUrl(x.fileId), ); })); }, ), ); }, ); }).toList(), ), ) : 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(widget.item.commentCount.toString()), onPressed: () => viewComments(context), ), TextButton.icon( icon: const Icon(Icons.emoji_emotions), label: Text(reactionCount.toString()), style: TextButton.styleFrom(foregroundColor: Colors.teal), onPressed: () => viewReactions(context), ), ], ), ), ], ); } }