Files
patbond-flutter/lib/features/post/post_detail_page.dart
T
2026-07-21 17:41:01 +08:00

278 lines
10 KiB
Dart

import 'package:flutter/material.dart';
import 'package:patbond_flutter/core/theme/app_theme.dart';
import 'package:patbond_flutter/data/demo_data.dart';
import 'package:patbond_flutter/models/models.dart';
import 'package:patbond_flutter/state/app_state.dart';
import 'package:patbond_flutter/widgets/common.dart';
class PostDetailPage extends StatefulWidget {
const PostDetailPage({
required this.appState,
required this.postId,
super.key,
});
final AppState appState;
final String postId;
@override
State<PostDetailPage> createState() => _PostDetailPageState();
}
class _PostDetailPageState extends State<PostDetailPage> {
final commentController = TextEditingController();
bool isFollowing = false;
@override
void dispose() {
commentController.dispose();
super.dispose();
}
PostModel get post =>
widget.appState.posts.firstWhere((item) => item.id == widget.postId);
void toggleLike() {
final current = post;
widget.appState.updatePost(
current.copyWith(
hasLiked: !current.hasLiked,
likes: current.hasLiked ? current.likes - 1 : current.likes + 1,
),
);
}
void sendComment() {
final text = commentController.text.trim();
if (text.isEmpty) return;
final current = post;
final comment = CommentModel(
id: 'comment_${DateTime.now().millisecondsSinceEpoch}',
authorName: '萌宠新手',
authorAvatar: userAvatar,
content: text,
time: '刚刚',
);
widget.appState.updatePost(
current.copyWith(comments: [comment, ...current.comments]),
);
commentController.clear();
FocusScope.of(context).unfocus();
}
@override
Widget build(BuildContext context) {
return AnimatedBuilder(
animation: widget.appState,
builder: (context, _) {
final current = post;
return Scaffold(
appBar: AppBar(
title: const Text(
'社区动态',
style: TextStyle(fontSize: 16, fontWeight: FontWeight.w800),
),
centerTitle: true,
actions: [
IconButton(
tooltip: '分享',
onPressed: () => ScaffoldMessenger.of(
context,
).showSnackBar(const SnackBar(content: Text('分享链接已准备好(演示)'))),
icon: const Icon(Icons.ios_share_outlined),
),
],
),
body: ListView(
padding: const EdgeInsets.only(bottom: 100),
children: [
AspectRatio(
aspectRatio: 1,
child: RemoteImage(url: current.mainImage),
),
Padding(
padding: const EdgeInsets.all(16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SectionCard(
child: Row(
children: [
RemoteImage(
url: current.authorAvatar,
width: 48,
height: 48,
borderRadius: BorderRadius.circular(24),
),
const SizedBox(width: 12),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
current.authorName,
style: Theme.of(
context,
).textTheme.titleMedium,
),
Text(
current.breedTag,
style: Theme.of(context).textTheme.bodySmall,
),
],
),
),
FilledButton.tonal(
onPressed: () =>
setState(() => isFollowing = !isFollowing),
child: Text(isFollowing ? '已关注' : '关注'),
),
],
),
),
const SizedBox(height: 14),
SectionCard(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(current.content),
const SizedBox(height: 14),
Wrap(
spacing: 8,
runSpacing: 8,
children: current.tags
.map((tag) => TagPill('#$tag'))
.toList(),
),
const SizedBox(height: 12),
Text(
'发布于 ${current.time}',
style: Theme.of(context).textTheme.bodySmall,
),
],
),
),
const SizedBox(height: 14),
Row(
children: [
FilledButton.tonalIcon(
onPressed: toggleLike,
icon: Icon(
current.hasLiked
? Icons.favorite
: Icons.favorite_border,
color: current.hasLiked ? Colors.red : null,
),
label: Text('${current.likes}'),
),
const SizedBox(width: 10),
FilledButton.tonalIcon(
onPressed: () {},
icon: const Icon(Icons.chat_bubble_outline),
label: Text('${current.comments.length}'),
),
const Spacer(),
IconButton.filledTonal(
onPressed: () => widget.appState.updatePost(
current.copyWith(
hasBookmarked: !current.hasBookmarked,
),
),
icon: Icon(
current.hasBookmarked
? Icons.bookmark
: Icons.bookmark_border,
color: current.hasBookmarked
? AppColors.primary
: null,
),
),
],
),
const SizedBox(height: 22),
Text(
'评论 (${current.comments.length})',
style: Theme.of(context).textTheme.titleLarge,
),
const SizedBox(height: 12),
...current.comments.map(
(comment) => Padding(
padding: const EdgeInsets.only(bottom: 12),
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
RemoteImage(
url: comment.authorAvatar,
width: 36,
height: 36,
borderRadius: BorderRadius.circular(18),
),
const SizedBox(width: 10),
Expanded(
child: SectionCard(
padding: const EdgeInsets.all(14),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
comment.authorName,
style: const TextStyle(
fontWeight: FontWeight.w700,
),
),
const SizedBox(height: 4),
Text(comment.content),
const SizedBox(height: 5),
Text(
comment.time,
style: Theme.of(
context,
).textTheme.bodySmall,
),
],
),
),
),
],
),
),
),
],
),
),
],
),
bottomSheet: SafeArea(
top: false,
child: Container(
color: Colors.white,
padding: const EdgeInsets.fromLTRB(12, 10, 12, 10),
child: Row(
children: [
Expanded(
child: TextField(
controller: commentController,
textInputAction: TextInputAction.send,
onSubmitted: (_) => sendComment(),
decoration: const InputDecoration(
hintText: '写下你的评论…',
isDense: true,
),
),
),
const SizedBox(width: 8),
IconButton.filled(
tooltip: '发送评论',
onPressed: sendComment,
icon: const Icon(Icons.send_rounded),
),
],
),
),
),
);
},
);
}
}