import 'package:cached_network_image/cached_network_image.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:go_router/go_router.dart'; import '../../../core/theme/app_theme.dart'; import '../../../models/video_item.dart'; import '../../../providers/auth_provider.dart'; /// 右侧互动栏(《01-开发文档》5.2.1): /// 作者头像(+关注预留)、点赞(红心+计数)、评论(气泡+计数)、收藏(星标+计数)、分享 class InteractionBar extends ConsumerWidget { const InteractionBar({ super.key, required this.item, required this.onLike, this.onFavorite, this.onComment, this.onShare, }); final VideoItem item; final void Function(int videoId) onLike; /// 收藏回调(与点赞一样由上层接当前策略的 feedProvider) final void Function(int videoId)? onFavorite; /// 评论入口(游客也可打开查看,发表时才守卫登录) final void Function(VideoItem item)? onComment; /// 分享入口(系统分享面板,无需登录) final void Function(VideoItem item)? onShare; @override Widget build(BuildContext context, WidgetRef ref) { return Column( mainAxisSize: MainAxisSize.min, children: [ // 作者头像(关注预留:右下角 + 号占位) _AuthorAvatar(item: item), const SizedBox(height: 20), _ActionItem( icon: item.isLiked ? Icons.favorite : Icons.favorite_border, color: item.isLiked ? AppColors.primary : Colors.white, count: item.likeCount, onTap: () => _guard(context, ref, () => onLike(item.videoId)), ), const SizedBox(height: 16), _ActionItem( icon: Icons.chat_bubble_outline, count: item.commentCount, onTap: () => onComment?.call(item), ), const SizedBox(height: 16), _ActionItem( icon: item.isFavorited ? Icons.star : Icons.star_border, color: item.isFavorited ? AppColors.gold : Colors.white, count: item.favoriteCount, onTap: () => _guard(context, ref, () => onFavorite?.call(item.videoId)), ), const SizedBox(height: 16), _ActionItem( icon: Icons.share_outlined, count: null, label: '分享', onTap: () => onShare?.call(item), ), ], ); } /// 登录守卫:未登录跳登录页 void _guard(BuildContext context, WidgetRef ref, VoidCallback action) { if (!ref.read(authProvider).isLoggedIn) { context.go('/login'); return; } action(); } } class _AuthorAvatar extends StatelessWidget { const _AuthorAvatar({required this.item}); final VideoItem item; @override Widget build(BuildContext context) { // 点头像进作者公开主页(游客可看) return GestureDetector( onTap: () => context.push('/user/${item.author.userId}'), child: SizedBox( width: 48, height: 56, child: Stack( children: [ CircleAvatar( radius: 24, backgroundColor: AppColors.surface, backgroundImage: item.author.avatarUrl.isNotEmpty ? CachedNetworkImageProvider(item.author.avatarUrl) : null, child: item.author.avatarUrl.isEmpty ? Text( item.author.nickname.isNotEmpty ? item.author.nickname.characters.first : '友', style: const TextStyle(color: Colors.white, fontSize: 18), ) : null, ), const Positioned( bottom: 0, left: 12, child: Icon(Icons.add_circle, size: 20, color: AppColors.primary), ), ], ), ), ); } } class _ActionItem extends StatelessWidget { const _ActionItem({ required this.icon, required this.onTap, this.count, this.label, this.color = Colors.white, }); final IconData icon; final VoidCallback onTap; final int? count; final String? label; final Color color; @override Widget build(BuildContext context) { return GestureDetector( onTap: onTap, behavior: HitTestBehavior.opaque, child: Column( mainAxisSize: MainAxisSize.min, children: [ Icon(icon, size: 32, color: color), const SizedBox(height: 2), Text( label ?? _formatCount(count ?? 0), style: const TextStyle( color: Colors.white, fontSize: 12, shadows: [Shadow(color: Colors.black54, blurRadius: 2)], ), ), ], ), ); } /// 计数格式化:≥10000 显示 x.xw static String _formatCount(int n) { if (n >= 10000) return '${(n / 10000).toStringAsFixed(1)}w'; return n.toString(); } }