Files
2026-09-15 15:44:13 +07:00

220 lines
6.9 KiB
Dart

import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:get/get.dart';
import 'package:hgdj/assets_tool/images.dart';
import 'package:hgdj/hj_page/home/provider/home_update_marker_provider.dart';
import 'package:hgdj/hj_utils/const.dart';
import 'package:hgdj/hj_utils/screen.dart';
import 'package:hgdj/tools_base/indicator/custom_tab_indicator.dart';
import 'package:hgdj/tools_base/loading/loading_center_widget.dart';
import 'package:hgdj/tools_base/widget/keep_alive_widget.dart';
import 'package:provider/provider.dart';
import '../cartoon/cartoon_sub_detail_page.dart';
import '../main_page/provider/bottom_bar_provider.dart';
import 'activity_float/home_float_widget.dart';
import 'home_drawer.dart';
import 'home_main_logic.dart';
import 'home_sub_module/home_tab_section_page.dart';
import 'home_sub_module/home_tab_sort_page.dart';
import 'search_page/widget/common_search_widget.dart';
class HomeMainPage extends StatelessWidget {
const HomeMainPage({super.key});
@override
Widget build(BuildContext context) {
return Material(
color: const Color(0xff050f17),
child: GetBuilder<HomeMainLogic>(
init: HomeMainLogic(),
tag: "HomeMainLogic",
builder: (logic) {
return Stack(
fit: StackFit.expand,
children: [
Scaffold(
key: logic.scaffoldKey,
endDrawer: HSHomeDrawer(homeLogic: logic),
body: _body(logic),
),
//右下角活动浮窗
const Positioned(right: 12, bottom: 40, child: HomeFloatWidget()),
],
);
},
),
);
}
Widget _body(HomeMainLogic logic) {
if (logic.isLoading) return const LoadingCenterWidget();
return Column(
children: [
//顶部搜索栏(状态栏 + 导航栏高度)
Container(
color: Colors.black,
padding: EdgeInsets.only(top: screen.paddingTop),
height: kToolbarHeight + screen.paddingTop,
child: CommonSearchBarView(logic: logic),
),
//排序变化时 tabViewKey 变,整个 TabView 连 TabController 一起重建
Expanded(
child: HomeTabView(key: ValueKey(logic.tabViewKey), logic: logic)),
],
);
}
}
class HomeTabView extends StatefulWidget {
final HomeMainLogic logic;
final bool isDarkStyle;
const HomeTabView({
super.key,
required this.logic,
this.isDarkStyle = false,
});
@override
State<HomeTabView> createState() => _HomeTabViewState();
}
class _HomeTabViewState extends State<HomeTabView>
with SingleTickerProviderStateMixin {
HomeMainLogic get logic => widget.logic;
bool get isDarkStyle => widget.isDarkStyle;
late final TabController tabCtr;
@override
void initState() {
super.initState();
final count = logic.tabs.length;
tabCtr = TabController(
// 防止 tab 数量不足时 initialIndex 越界导致断言崩溃
initialIndex: count > 0 ? logic.selectedTabIndex.clamp(0, count - 1) : 0,
length: count,
vsync: this,
);
tabCtr.addListener(_onTabChange);
logic.tabCtr = tabCtr;
}
@override
void dispose() {
// controller 在本 State vsync 创建,归本 State 释放(排序换 key 会重建 State)
tabCtr.removeListener(_onTabChange);
tabCtr.dispose();
// 换 key 重建时新 State 可能已把自己的 ctr 写进 logic,只清掉自己那一份
if (identical(logic.tabCtr, tabCtr)) logic.tabCtr = null;
super.dispose();
}
void _onTabChange() {
if (tabCtr.indexIsChanging) return;
if (isDarkStyle) {
DarkwebBottomProvider().setScrollController(tabCtr.index);
return;
}
HomeBottomProvider().setScrollController(tabCtr.index);
final tabs = logic.tabs;
if (tabCtr.index < tabs.length && tabs[tabCtr.index].id == '-110') {
// 进入「最新」:清 Tab 红点;默认排序即「今日最新」,一并视为已查看
HomeUpdateMarkerProvider().markHomeLatestViewed();
HomeUpdateMarkerProvider().markTodayLatestViewed();
}
}
@override
Widget build(BuildContext context) {
return Column(
children: [
Container(
height: 48.h,
color: Colors.black,
child: _tabBar(),
),
Expanded(
child: Stack(
fit: StackFit.expand,
children: [
if (isDarkStyle) Image.asset("aw_bg.webp".homePath),
TabBarView(
controller: tabCtr,
children: [
for (int i = 0; i < logic.tabs.length; i++) _tabPage(i)
],
),
],
),
),
],
);
}
Widget _tabBar() {
return Consumer<HomeUpdateMarkerProvider>(
builder: (_, marker, __) {
return TabBar(
tabAlignment: TabAlignment.start,
tabs: logic.tabs.map((e) {
//「最新」有更新时右上角挂红点
final showDot =
!isDarkStyle && e.id == '-110' && marker.showHomeLatestDot;
return Container(
padding: EdgeInsets.symmetric(horizontal: 14.w),
alignment: Alignment.center,
child: Stack(
clipBehavior: Clip.none,
children: [
Text(e.moduleName ?? ''),
if (showDot)
Positioned(
right: -8,
top: -2,
child: HomeUpdateMarkerProvider.buildRedDot(),
),
],
),
);
}).toList(),
isScrollable: true,
padding: const EdgeInsets.only(bottom: 2),
labelPadding: EdgeInsets.zero,
unselectedLabelStyle: const TextStyle(fontSize: 14),
unselectedLabelColor: const Color(0x73FFFFFF),
labelStyle:
const TextStyle(fontSize: 16, fontWeight: FontWeight.w500),
labelColor:
isDarkStyle ? const Color(0xff810906) : const Color(0xE5FFFFFF),
indicator: CustomIndicator(
height: 2,
width: 16.w,
color: const Color(0xfff68804),
offsetY: 4,
),
controller: tabCtr,
);
},
);
}
/// 按 module type/showType/isACG 分发到对应子页,统一 keepAlive
Widget _tabPage(int index) {
final module = logic.tabs[index];
if (module.type == 1 || module.type == 3) {
//showType==2 走分区聚合页,其余走排序列表页
return module.showType == 2
? HomeTabSectionPage(index, module, isDarkStyle: isDarkStyle)
.keepAlive
: HomeTabSortPage(index, module, isDarkStyle: isDarkStyle).keepAlive;
}
if (module.isACG) {
return CartoonSubDetailPage(tagData: module, type: MediaStyle.Cartoon)
.keepAlive;
}
return HomeTabSortPage(index, module, isDarkStyle: isDarkStyle).keepAlive;
}
}