This repository has been archived on 2024-06-08. You can view files and clone it, but cannot push or open issues or pull requests.
SolarAgent/lib/widgets/feed.dart

178 lines
5.6 KiB
Dart
Raw Normal View History

2024-03-23 23:05:04 +08:00
import 'package:flutter/material.dart';
2024-03-24 00:13:52 +08:00
import 'package:flutter_carousel_widget/flutter_carousel_widget.dart';
2024-03-23 23:05:04 +08:00
import 'package:flutter_markdown/flutter_markdown.dart';
import 'package:go_router/go_router.dart';
2024-03-23 23:05:04 +08:00
import 'package:solaragent/models/feed.dart';
import 'package:solaragent/router.dart';
2024-03-24 00:13:52 +08:00
import 'package:solaragent/widgets/image.dart';
2024-03-24 12:12:13 +08:00
import 'package:solaragent/widgets/posts/comments.dart';
2024-03-24 22:23:23 +08:00
import 'package:solaragent/widgets/posts/content/article.dart';
import 'package:solaragent/widgets/posts/content/moment.dart';
2024-03-24 13:34:29 +08:00
import 'package:solaragent/widgets/posts/reactions.dart';
2024-03-23 23:05:04 +08:00
2024-03-24 13:34:29 +08:00
class FeedItem extends StatefulWidget {
2024-03-23 23:05:04 +08:00
final Feed item;
2024-03-24 22:23:23 +08:00
final bool? brief;
2024-03-23 23:05:04 +08:00
2024-03-24 22:23:23 +08:00
const FeedItem({super.key, required this.item, this.brief});
2024-03-23 23:05:04 +08:00
2024-03-24 13:34:29 +08:00
@override
State<FeedItem> createState() => _FeedItemState();
}
class _FeedItemState extends State<FeedItem> {
int reactionCount = 0;
Map<String, dynamic>? reactionList;
2024-03-24 12:12:13 +08:00
void viewComments(BuildContext context) {
showModalBottomSheet(
context: context,
isScrollControlled: true,
2024-03-24 13:34:29 +08:00
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;
});
},
),
2024-03-24 12:12:13 +08:00
);
}
2024-03-24 00:13:52 +08:00
bool hasAttachments() =>
2024-03-24 22:23:23 +08:00
widget.item.modelType == "moment" &&
widget.item.attachments != null &&
widget.item.attachments!.isNotEmpty;
2024-03-24 00:13:52 +08:00
2024-03-23 23:05:04 +08:00
String getDescription(String desc) =>
desc.isEmpty ? "No description yet." : desc;
2024-03-24 00:13:52 +08:00
String getFileUrl(String fileId) =>
'https://co.solsynth.dev/api/attachments/o/$fileId';
2024-03-24 22:23:23 +08:00
Widget buildContent() {
switch (widget.item.modelType) {
case "article":
return ArticleContent(item: widget.item, brief: widget.brief ?? false);
default:
return MomentContent(item: widget.item, brief: widget.brief ?? false);
2024-03-24 22:23:23 +08:00
}
}
Widget buildItem(BuildContext context) {
2024-03-24 01:22:01 +08:00
return Column(
children: [
Container(
color: Colors.grey[50],
child: ListTile(
2024-03-24 13:34:29 +08:00
title: Text(widget.item.author.name),
2024-03-24 01:22:01 +08:00
leading: CircleAvatar(
2024-03-24 13:34:29 +08:00
backgroundImage: NetworkImage(widget.item.author.avatar),
2024-03-24 01:22:01 +08:00
),
subtitle: Text(
2024-03-24 13:34:29 +08:00
getDescription(widget.item.author.description),
2024-03-24 01:22:01 +08:00
overflow: TextOverflow.ellipsis,
maxLines: 1,
softWrap: false,
2024-03-23 23:05:04 +08:00
),
),
2024-03-24 01:22:01 +08:00
),
2024-03-24 22:23:23 +08:00
buildContent(),
2024-03-24 01:22:01 +08:00
hasAttachments()
? Container(
decoration: const BoxDecoration(
border: Border(
top: BorderSide(width: 0.3, color: Color(0xffdedede))),
),
child: FlutterCarousel(
options: CarouselOptions(
2024-03-24 22:23:23 +08:00
height: 360.0,
2024-03-24 11:20:59 +08:00
viewportFraction: 1.0,
2024-03-24 01:22:01 +08:00
showIndicator: true,
slideIndicator: const CircularSlideIndicator(),
2024-03-24 00:13:52 +08:00
),
2024-03-24 13:34:29 +08:00
items: widget.item.attachments?.map((x) {
2024-03-24 01:22:01 +08:00
return Builder(
builder: (BuildContext context) {
2024-03-24 11:20:59 +08:00
return SizedBox(
2024-03-24 01:22:01 +08:00
width: MediaQuery.of(context).size.width,
child: InkWell(
child: Image.network(
getFileUrl(x.fileId),
fit: BoxFit.cover,
2024-03-24 00:13:52 +08:00
),
2024-03-24 01:22:01 +08:00
onTap: () {
Navigator.push(context,
MaterialPageRoute(builder: (_) {
return ImageLightbox(
url: getFileUrl(x.fileId),
);
}));
},
),
);
},
);
}).toList(),
),
)
: Container(),
2024-03-24 12:12:13 +08:00
Container(
padding: const EdgeInsets.symmetric(horizontal: 8),
decoration: const BoxDecoration(
2024-03-24 22:23:23 +08:00
border: Border(
top: BorderSide(width: 0.3, color: Color(0xffdedede)),
),
2024-03-24 12:12:13 +08:00
),
child: Row(
children: [
TextButton.icon(
icon: const Icon(Icons.comment),
2024-03-24 13:34:29 +08:00
label: Text(widget.item.commentCount.toString()),
2024-03-24 12:12:13 +08:00
onPressed: () => viewComments(context),
2024-03-24 13:34:29 +08:00
),
TextButton.icon(
icon: const Icon(Icons.emoji_emotions),
label: Text(reactionCount.toString()),
style: TextButton.styleFrom(foregroundColor: Colors.teal),
onPressed: () => viewReactions(context),
),
2024-03-24 12:12:13 +08:00
],
),
),
2024-03-24 01:22:01 +08:00
],
2024-03-23 23:05:04 +08:00
);
}
@override
void initState() {
reactionCount = widget.item.reactionCount;
reactionList = widget.item.reactionList ?? <String, dynamic>{};
super.initState();
}
@override
Widget build(BuildContext context) {
return (widget.brief ?? false)
? GestureDetector(
child: buildItem(context),
onTap: () => router.push(
"/post/${widget.item.modelType}/${widget.item.alias}",
),
)
: buildItem(context);
}
2024-03-23 23:05:04 +08:00
}