Files
wushu/lib/views/home/home_page.dart
2026-04-02 07:06:55 +08:00

262 lines
9.7 KiB
Dart
Raw 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.
/// 时间: 2025-03-22
/// 功能: 诗词主页(参考微信小程序布局)
/// 介绍: 展示诗词内容支持点赞、收藏、分享等功能参考wxpm小程序的index页面布局
/// 最新变化: 2026-04-02 支持深色模式,添加底部内边距适配液态玻璃导航栏
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import '../../constants/app_constants.dart';
import '../../config/app_config.dart';
import '../../../services/get/home_controller.dart';
import '../../../services/get/theme_controller.dart';
import 'home_part.dart';
import 'set/home_components.dart';
import 'set/home-load.dart';
import 'set/home-set.dart';
class HomePage extends StatefulWidget {
const HomePage({super.key});
@override
State<HomePage> createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
final GlobalKey repaintKey = GlobalKey();
final SecondaryButtonsManager _secondaryButtonsManager =
SecondaryButtonsManager();
final FloatingButtonsVisibilityManager _floatingButtonsVisibilityManager =
FloatingButtonsVisibilityManager();
@override
void initState() {
super.initState();
_secondaryButtonsManager.init();
_floatingButtonsVisibilityManager.init();
}
@override
void dispose() {
_floatingButtonsVisibilityManager.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
Get.lazyPut(() => HomeController());
final controller = Get.find<HomeController>();
final themeController = Get.find<ThemeController>();
return Obx(() {
final isDark = themeController.isDarkModeRx.value;
return Scaffold(
backgroundColor: isDark ? const Color(0xFF121212) : Colors.grey[50],
body: SafeArea(child: _buildBody(controller, isDark)),
);
});
}
Widget _buildBody(HomeController controller, bool isDark) {
if (controller.loading.value) {
return LoadingWidget(isDark: isDark);
}
if (controller.errorMessage.value.isNotEmpty) {
return CustomErrorWidget(
errorMessage: controller.errorMessage.value,
onRetry: controller.loadPoetry,
isDark: isDark,
);
}
if (!PoetryDataUtils.isValidPoetryData(controller.poetryData.value)) {
return EmptyWidget(isDark: isDark);
}
return _buildContent(controller, isDark);
}
Widget _buildContent(HomeController controller, bool isDark) {
return FutureBuilder<bool>(
future: OfflineDataManager().isOnline(),
builder: (context, snapshot) {
final isOnline = snapshot.data ?? true;
return Stack(
children: [
RefreshIndicator(
onRefresh: controller.refreshPoetry,
child: SingleChildScrollView(
physics: const AlwaysScrollableScrollPhysics(),
// 添加底部内边距,让内容延伸到导航栏下方,实现玻璃效果
padding: EdgeInsets.only(
top: 48,
bottom: AppConfig.liquidGlassTotalHeight + 16,
),
child: Column(
children: [
Obx(
() => PoetryCard(
poetryData: controller.poetryData.value!,
keywordList: List.from(controller.keywordList),
onTap: controller.loadNextPoetry,
sectionLoadingStates: Map.from(
controller.sectionLoadingStates,
),
repaintKey: repaintKey,
isDark: isDark,
),
),
const SizedBox(height: 160),
],
),
),
),
// 收起/恢复按钮 - 右上角(与下方分享按钮对齐)
Positioned(
top: 8,
right: 16,
child: FloatingButtonsToggleButton(
manager: _floatingButtonsVisibilityManager,
isDark: isDark,
),
),
// 左侧按钮组 - 固定位置紧贴底栏bar
ValueListenableBuilder<bool>(
valueListenable:
_floatingButtonsVisibilityManager.flashingNotifier,
builder: (context, isFlashing, child) {
return ValueListenableBuilder<bool>(
valueListenable:
_floatingButtonsVisibilityManager.visibleNotifier,
builder: (context, isVisible, child) {
if (!isVisible && !isFlashing) {
return const SizedBox.shrink();
}
return ValueListenableBuilder<bool>(
valueListenable: _secondaryButtonsManager.hiddenNotifier,
builder: (context, isHidden, child) {
if (isHidden) return const SizedBox.shrink();
return Positioned(
left: 16,
bottom:
AppConfig.liquidGlassHeight +
AppConfig.liquidGlassBottomMargin +
68,
child: FloatingPreviousButton(
onPrevious: controller.loadPreviousPoetry,
isDark: isDark,
),
);
},
);
},
);
},
),
ValueListenableBuilder<bool>(
valueListenable:
_floatingButtonsVisibilityManager.flashingNotifier,
builder: (context, isFlashing, child) {
return ValueListenableBuilder<bool>(
valueListenable:
_floatingButtonsVisibilityManager.visibleNotifier,
builder: (context, isVisible, child) {
if (!isVisible && !isFlashing) {
return const SizedBox.shrink();
}
return Positioned(
left: 16,
bottom:
AppConfig.liquidGlassHeight +
AppConfig.liquidGlassBottomMargin +
8,
child: FloatingNextButton(
onNext: controller.loadNextPoetry,
isDark: isDark,
),
);
},
);
},
),
// 右侧按钮组 - 固定位置紧贴底栏bar
ValueListenableBuilder<bool>(
valueListenable:
_floatingButtonsVisibilityManager.flashingNotifier,
builder: (context, isFlashing, child) {
return ValueListenableBuilder<bool>(
valueListenable:
_floatingButtonsVisibilityManager.visibleNotifier,
builder: (context, isVisible, child) {
if (!isVisible && !isFlashing) {
return const SizedBox.shrink();
}
return ValueListenableBuilder<bool>(
valueListenable: _secondaryButtonsManager.hiddenNotifier,
builder: (context, isHidden, child) {
if (isHidden) return const SizedBox.shrink();
return Positioned(
right: 16,
bottom:
AppConfig.liquidGlassHeight +
AppConfig.liquidGlassBottomMargin +
68,
child: FloatingShareButton(
onShare: () async {
if (controller.poetryData.value != null) {
await ShareImageUtils.captureAndShare(
context,
repaintKey,
subject: controller.poetryData.value!.name,
);
}
},
isDark: isDark,
),
);
},
);
},
);
},
),
if (isOnline)
ValueListenableBuilder<bool>(
valueListenable:
_floatingButtonsVisibilityManager.flashingNotifier,
builder: (context, isFlashing, child) {
return ValueListenableBuilder<bool>(
valueListenable:
_floatingButtonsVisibilityManager.visibleNotifier,
builder: (context, isVisible, child) {
if (!isVisible && !isFlashing) {
return const SizedBox.shrink();
}
return Positioned(
right: 16,
bottom:
AppConfig.liquidGlassHeight +
AppConfig.liquidGlassBottomMargin +
8,
child: Obx(
() => FloatingLikeButton(
isLiked: controller.isLiked.value,
isLoadingLike: controller.isLoadingLike.value,
onToggleLike: controller.toggleLike,
isDark: isDark,
),
),
);
},
);
},
),
],
);
},
);
}
}