119 lines
3.9 KiB
Dart
119 lines
3.9 KiB
Dart
import 'package:flutter/material.dart';
|
|
import 'package:go_router/go_router.dart';
|
|
|
|
import '../../../core/theme/app_theme.dart';
|
|
import '../../../models/video_item.dart';
|
|
|
|
/// 左下信息区(《01-开发文档》5.2.1):
|
|
/// 作者昵称、标题(标题后 #标签,点击跳转标签视频页)、描述(展开/收起)
|
|
class VideoInfoSection extends StatefulWidget {
|
|
const VideoInfoSection({super.key, required this.item});
|
|
|
|
final VideoItem item;
|
|
|
|
@override
|
|
State<VideoInfoSection> createState() => _VideoInfoSectionState();
|
|
}
|
|
|
|
class _VideoInfoSectionState extends State<VideoInfoSection> {
|
|
bool _expanded = false;
|
|
|
|
static String _fmtSeconds(int seconds) {
|
|
final h = seconds ~/ 3600;
|
|
final m = ((seconds % 3600) ~/ 60).toString().padLeft(2, '0');
|
|
final s = (seconds % 60).toString().padLeft(2, '0');
|
|
return h > 0 ? '$h:$m:$s' : '$m:$s';
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
final item = widget.item;
|
|
return Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
mainAxisSize: MainAxisSize.min,
|
|
children: [
|
|
// 昵称
|
|
Text(
|
|
'@${item.author.nickname}',
|
|
style: const TextStyle(
|
|
color: Colors.white,
|
|
fontSize: 16,
|
|
fontWeight: FontWeight.w700,
|
|
shadows: [Shadow(color: Colors.black54, blurRadius: 4)],
|
|
),
|
|
),
|
|
const SizedBox(height: 8),
|
|
|
|
// 标题 + 时长 + #标签(点击标签跳转标签视频页)
|
|
Wrap(
|
|
crossAxisAlignment: WrapCrossAlignment.center,
|
|
spacing: 6,
|
|
runSpacing: 4,
|
|
children: [
|
|
if (item.title.isNotEmpty)
|
|
Text(
|
|
item.title,
|
|
style: const TextStyle(
|
|
color: Colors.white,
|
|
fontSize: 15,
|
|
shadows: [Shadow(color: Colors.black54, blurRadius: 4)],
|
|
),
|
|
),
|
|
// 标题后显示视频时长
|
|
if (item.duration > 0)
|
|
Container(
|
|
padding:
|
|
const EdgeInsets.symmetric(horizontal: 5, vertical: 1),
|
|
decoration: BoxDecoration(
|
|
color: Colors.black38,
|
|
borderRadius: BorderRadius.circular(4),
|
|
border: Border.all(color: Colors.white24, width: 0.5),
|
|
),
|
|
child: Text(
|
|
_fmtSeconds(item.duration),
|
|
style: const TextStyle(
|
|
color: Colors.white70,
|
|
fontSize: 11,
|
|
shadows: [Shadow(color: Colors.black54, blurRadius: 4)],
|
|
),
|
|
),
|
|
),
|
|
for (final tag in item.tags)
|
|
GestureDetector(
|
|
onTap: () => context.push('/tags/${Uri.encodeComponent(tag)}'),
|
|
child: Text(
|
|
'#$tag',
|
|
style: const TextStyle(
|
|
color: AppColors.secondary,
|
|
fontSize: 15,
|
|
fontWeight: FontWeight.w600,
|
|
shadows: [Shadow(color: Colors.black54, blurRadius: 4)],
|
|
),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
|
|
// 描述(展开/收起)
|
|
if (item.description.isNotEmpty) ...[
|
|
const SizedBox(height: 6),
|
|
GestureDetector(
|
|
onTap: () => setState(() => _expanded = !_expanded),
|
|
child: Text(
|
|
item.description,
|
|
maxLines: _expanded ? null : 1,
|
|
overflow: _expanded ? null : TextOverflow.ellipsis,
|
|
style: const TextStyle(color: AppColors.textSecondary, fontSize: 13),
|
|
),
|
|
),
|
|
if (!_expanded && item.description.length > 30)
|
|
const Text(
|
|
'展开',
|
|
style: TextStyle(color: AppColors.textWeak, fontSize: 12),
|
|
),
|
|
],
|
|
],
|
|
);
|
|
}
|
|
}
|