Files
2026-10-24 00:04:50 +08:00

99 lines
3.3 KiB
Dart
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import '../../core/theme/app_theme.dart';
import '../../providers/feed_provider.dart';
import '../../screens/category/category_screen.dart';
import '../../screens/feed/feed_screen.dart';
import '../../screens/notification/notifications_screen.dart';
import '../../screens/profile/mine_screen.dart';
import '../../screens/upload/upload_screen.dart';
/// 首页壳:底部 Tab(首页/分类/发布/消息/我的),02-技术文档信息架构
/// IndexedStack 保活各 Tab 状态(Feed 播放器池 / 分类滚动位置 / 上传流程不被销毁)
class HomeShell extends ConsumerStatefulWidget {
const HomeShell({super.key});
@override
ConsumerState<HomeShell> createState() => _HomeShellState();
}
class _HomeShellState extends ConsumerState<HomeShell> {
int _index = 0;
/// Feed 三种策略的 provider keys(切 Tab 时用于暂停/恢复播放器池)
static const _feedStrategies = FeedStrategy.values;
void _onTabSelected(int i) {
if (i == _index) return;
// 切到非首页:挂起所有 Feed 策略池——suspend 记录断点后 stop 全槽位
// (mpv pause 停不住 HLS 预读,只有 stop 能可靠断下载);
// 回首页 rebind 重新 open + seek 断点续播,缓存分片零流量(抖音行为)
if (i != 0) {
for (final s in _feedStrategies) {
ref.read(feedProvider(s).notifier).pool.suspend();
}
}
ref.read(feedTabVisibleProvider.notifier).state = i == 0;
setState(() => _index = i);
// 切回首页:只恢复当前选中策略的池(其余保持挂起)
if (i == 0) {
final active = ref.read(activeFeedStrategyProvider);
final notifier = ref.read(feedProvider(active).notifier);
unawaited(() async {
await notifier.pool.resume();
// 兜底:挂起期间首屏 bind 可能尚未发生,补一次当前页绑定播放
await notifier.rebindCurrent();
}());
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: IndexedStack(
index: _index,
children: const [
FeedScreen(),
CategoryScreen(),
UploadScreen(),
NotificationsScreen(),
MineScreen(),
],
),
bottomNavigationBar: NavigationBar(
height: 60,
backgroundColor: AppColors.surface,
indicatorColor: AppColors.primary.withValues(alpha: 0.2),
selectedIndex: _index,
onDestinationSelected: _onTabSelected,
destinations: const [
NavigationDestination(
icon: Icon(Icons.home_outlined),
selectedIcon: Icon(Icons.home, color: AppColors.primary),
label: '首页',
),
NavigationDestination(
icon: Icon(Icons.grid_view_outlined),
label: '分类',
),
NavigationDestination(
icon: Icon(Icons.add_box_outlined),
label: '发布',
),
NavigationDestination(
icon: Icon(Icons.notifications_none),
label: '消息',
),
NavigationDestination(
icon: Icon(Icons.person_outline),
label: '我的',
),
],
),
);
}
}