Files
DMZJ_F/lib/modules/index/windows_index_page.dart
2026-03-07 17:24:59 +08:00

151 lines
5.0 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 'package:fluent_ui/fluent_ui.dart' as fluent;
import 'package:flutter/material.dart';
import 'package:flutter_dmzj/app/platform_utils.dart';
import 'package:flutter_dmzj/modules/common/empty_page.dart';
import 'package:flutter_dmzj/modules/index/index_controller.dart';
import 'package:flutter_dmzj/routes/app_navigator.dart';
import 'package:flutter_dmzj/routes/app_pages.dart';
import 'package:get/get.dart';
import 'package:remixicon/remixicon.dart';
/// Windows平台专用导航页面 - 使用Fluent UI的NavigationView
class WindowsIndexPage extends GetView<IndexController> {
const WindowsIndexPage({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return fluent.FluentTheme(
data: PlatformUtils.getFluentTheme(context),
child: Obx(
() => fluent.NavigationView(
paneBodyBuilder: (item, body) {
// Builder ensures ctx is INSIDE the FluentTheme ancestor tree
return Builder(
builder: (ctx) => KeyedSubtree(
key: const ValueKey('windows_main_content'),
child: _buildMasterDetail(ctx),
),
);
},
pane: fluent.NavigationPane(
selected: controller.index.value,
onChanged: controller.setIndex,
displayMode: fluent.PaneDisplayMode.auto,
indicator: const fluent.StickyNavigationIndicator(),
items: [
fluent.PaneItem(
icon: const Icon(Remix.bear_smile_line),
title: const Text('漫画'),
body: const SizedBox.shrink(),
),
fluent.PaneItem(
icon: const Icon(Remix.article_line),
title: const Text('资讯'),
body: const SizedBox.shrink(),
),
fluent.PaneItem(
icon: const Icon(Remix.book_open_line),
title: const Text('轻小说'),
body: const SizedBox.shrink(),
),
],
footerItems: [
fluent.PaneItem(
icon: const Icon(Remix.user_smile_line),
title: const Text('我的'),
body: const SizedBox.shrink(),
),
],
),
),
),
);
}
/// 主内容区section列表(左) + 子路由详情(右)
/// 使用Material主题颜色避免FluentTheme.of()需要特定祖先
Widget _buildMasterDetail(BuildContext context) {
final materialTheme = Theme.of(context);
final isDark = materialTheme.brightness == Brightness.dark;
// 使用Material主题颜色衍生背景色
final scaffoldBg = materialTheme.scaffoldBackgroundColor;
final panelBg = isDark ? const Color(0xff202020) : const Color(0xfff0f0f0);
final dividerColor = materialTheme.dividerColor;
return ColoredBox(
color: scaffoldBg,
child: Row(
children: [
// 左侧各模块首页IndexedStack切换
SizedBox(
width: 450,
child: ColoredBox(
color: panelBg,
child: Obx(
() => IndexedStack(
key: controller.indexKey,
index: controller.index.value,
children: controller.pages,
),
),
),
),
// 分隔线
Container(width: 1, color: dividerColor),
// 右侧:子路由(详情页、阅读器等)
Expanded(
child: _buildContentNavigator(),
),
],
),
);
}
/// 子路由导航器(处理详情页、阅读器等)
Widget _buildContentNavigator() {
return PopScope(
canPop: false,
onPopInvoked: (didPop) {
if (!didPop) {
if (Navigator.canPop(Get.context!)) {
Get.back();
return;
}
if (AppNavigator.subNavigatorKey!.currentState!.canPop()) {
AppNavigator.subNavigatorKey!.currentState!.pop();
}
}
},
child: ClipRect(
child: Navigator(
key: AppNavigator.subNavigatorKey,
initialRoute: '/',
onUnknownRoute: (settings) => GetPageRoute(
page: () => const EmptyPage(),
),
observers: [WindowsSubNavigatorObserver()],
onGenerateRoute: AppPages.generateSubRoute,
),
),
);
}
}
/// Windows子路由监听不需要更新showContent因为采用固定master-detail布局
class WindowsSubNavigatorObserver extends NavigatorObserver {
@override
void didPush(Route route, Route? previousRoute) {
super.didPush(route, previousRoute);
if (previousRoute != null) {
final routeName = route.settings.name ?? '';
AppNavigator.currentContentRouteName = routeName;
}
}
@override
void didPop(Route route, Route? previousRoute) {
super.didPop(route, previousRoute);
final routeName = previousRoute?.settings.name ?? '';
AppNavigator.currentContentRouteName = routeName;
}
}