151 lines
5.0 KiB
Dart
151 lines
5.0 KiB
Dart
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;
|
||
}
|
||
}
|