import 'package:flutter/material.dart'; import '../../core/api/services/image_api.dart'; import '../../core/auth/auth_service.dart'; import '../../core/user/account_refresh.dart'; import '../../core/user/user_state.dart'; import '../../core/theme/app_spacing.dart'; import '../../shared/widgets/top_nav_bar.dart'; import 'models/category_item.dart'; import 'models/task_item.dart'; import 'widgets/home_tab_row.dart'; import 'widgets/video_card.dart'; /// AI Video App home screen - tab 来自分类接口,Grid 来自任务列表接口 class HomeScreen extends StatefulWidget { const HomeScreen({super.key, this.isActive = true}); final bool isActive; @override State createState() => _HomeScreenState(); } class _HomeScreenState extends State { List _categories = []; CategoryItem? _selectedCategory; List _tasks = []; bool _categoriesLoading = true; bool _tasksLoading = false; int? _activeCardIndex; @override void initState() { super.initState(); _loadCategories(); if (widget.isActive) refreshAccount(); } @override void didUpdateWidget(covariant HomeScreen oldWidget) { super.didUpdateWidget(oldWidget); if (widget.isActive && !oldWidget.isActive) { refreshAccount(); } } Future _loadCategories() async { setState(() => _categoriesLoading = true); await AuthService.loginComplete; if (!mounted) return; final res = await ImageApi.getCategoryList(); if (mounted) { if (res.isSuccess && res.data is List) { final list = (res.data as List) .map((e) => CategoryItem.fromJson(e as Map)) .toList(); setState(() { _categories = list; _selectedCategory = list.isNotEmpty ? list.first : null; if (_selectedCategory != null) _loadTasks(_selectedCategory!.id); }); } else { setState(() => _categories = []); } setState(() => _categoriesLoading = false); } } Future _loadTasks(int categoryId) async { setState(() => _tasksLoading = true); final res = await ImageApi.getImg2VideoTasks(insignia: categoryId); if (mounted) { if (res.isSuccess && res.data is List) { final list = (res.data as List) .map((e) => TaskItem.fromJson(e as Map)) .toList(); setState(() { _tasks = list; _activeCardIndex = null; }); } else { setState(() => _tasks = []); } setState(() => _tasksLoading = false); } } void _onTabChanged(CategoryItem c) { setState(() => _selectedCategory = c); _loadTasks(c.id); } static const _placeholderImage = 'https://images.unsplash.com/photo-1763929272543-0df093e4f659?w=400'; @override Widget build(BuildContext context) { return Scaffold( backgroundColor: const Color(0xFFFAFAFA), appBar: PreferredSize( preferredSize: const Size.fromHeight(56), child: TopNavBar( title: 'PetsHero AI', credits: UserCreditsData.of(context)?.creditsDisplay ?? '--', onCreditsTap: () => Navigator.of(context).pushNamed('/recharge'), ), ), body: Column( children: [ Padding( padding: const EdgeInsets.symmetric( horizontal: AppSpacing.screenPadding, vertical: AppSpacing.xs, ), child: _categoriesLoading ? const SizedBox( height: 40, child: Center(child: CircularProgressIndicator())) : HomeTabRow( categories: _categories, selectedId: _selectedCategory?.id ?? -1, onTabChanged: _onTabChanged, ), ), Expanded( child: _tasksLoading ? const Center(child: CircularProgressIndicator()) : LayoutBuilder( builder: (context, constraints) { return Center( child: ConstrainedBox( constraints: const BoxConstraints(maxWidth: 390), child: GridView.builder( padding: const EdgeInsets.fromLTRB( AppSpacing.screenPadding, AppSpacing.xl, AppSpacing.screenPadding, AppSpacing.screenPaddingLarge, ), gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount( crossAxisCount: 2, childAspectRatio: 165 / 248, mainAxisSpacing: AppSpacing.xl, crossAxisSpacing: AppSpacing.xl, ), itemCount: _tasks.length, itemBuilder: (context, index) { final task = _tasks[index]; final credits = task.credits480p != null ? task.credits480p.toString() : '50'; return VideoCard( imageUrl: task.previewImageUrl ?? _placeholderImage, videoUrl: task.previewVideoUrl, credits: credits, isActive: _activeCardIndex == index, onPlayRequested: () => setState(() => _activeCardIndex = index), onStopRequested: () => setState(() => _activeCardIndex = null), onGenerateSimilar: () => Navigator.of(context).pushNamed( '/generate', arguments: task, ), ); }, ), ), ); }, ), ), ], ), ); } }