- 移除多个文件中的无用参数如sortOrder、keyword、limit等 - 优化日期处理逻辑,使用DateTime(year)替代DateTime(year,1,1) - 修复颜色和边框样式的一致性 - 更新API调用参数,移除冗余的limit和page参数 - 新增SessionPopupMenu组件和ChatSession模型 - 优化笔记模型的时间显示和类型转换 - 修复验证码发送逻辑和加载状态 - 更新文档和脚本文件
160 lines
6.2 KiB
Dart
160 lines
6.2 KiB
Dart
// ============================================================
|
||
// 闲言APP — 应用布局壳
|
||
// 创建时间: 2026-04-20
|
||
// 更新时间: 2026-04-30
|
||
// 作用: ShellRoute 布局壳,包含底部 GlassBottomBar 导航 + 灵感小红点
|
||
// 上次更新: 灵感Tab接入badges小红点,显示未读推送数
|
||
// ============================================================
|
||
|
||
import 'package:badges/badges.dart' as badges;
|
||
import 'package:flutter/cupertino.dart';
|
||
import 'package:flutter/material.dart';
|
||
import 'package:flutter/services.dart';
|
||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||
import 'package:go_router/go_router.dart';
|
||
import 'package:liquid_glass_widgets/liquid_glass_widgets.dart';
|
||
|
||
import '../theme/app_theme.dart';
|
||
import '../utils/interaction_animations.dart';
|
||
import '../../features/inspiration/presentation/widgets/tool_panel.dart';
|
||
import '../../features/inspiration/providers/chat_provider.dart';
|
||
|
||
class AppShell extends ConsumerWidget {
|
||
const AppShell({super.key, required this.child});
|
||
|
||
final StatefulNavigationShell child;
|
||
|
||
@override
|
||
Widget build(BuildContext context, WidgetRef ref) {
|
||
final ext = AppTheme.ext(context);
|
||
final int currentIndex = child.currentIndex;
|
||
final unreadCount = ref.watch(chatProvider).unreadCount;
|
||
|
||
return CelebrationOverlay(
|
||
child: AnnotatedRegion<SystemUiOverlayStyle>(
|
||
value: const SystemUiOverlayStyle(
|
||
statusBarColor: Colors.black,
|
||
statusBarIconBrightness: Brightness.light,
|
||
statusBarBrightness: Brightness.dark,
|
||
systemNavigationBarColor: Colors.black,
|
||
systemNavigationBarIconBrightness: Brightness.light,
|
||
systemNavigationBarDividerColor: Colors.black,
|
||
),
|
||
child: PopScope(
|
||
canPop: false,
|
||
onPopInvokedWithResult: (didPop, _) {
|
||
if (didPop) return;
|
||
},
|
||
child: Scaffold(
|
||
extendBody: true,
|
||
body: Stack(children: [child, const ToolPanel()]),
|
||
bottomNavigationBar: GlassBottomBar(
|
||
tabs: [
|
||
const GlassBottomBarTab(
|
||
label: '首页',
|
||
icon: Icon(CupertinoIcons.house),
|
||
activeIcon: Icon(CupertinoIcons.house_fill),
|
||
glowColor: Color(0xFFE8E8ED),
|
||
),
|
||
GlassBottomBarTab(
|
||
label: '灵感',
|
||
icon: badges.Badge(
|
||
showBadge: unreadCount > 0,
|
||
badgeContent: Text(
|
||
'$unreadCount',
|
||
style: const TextStyle(
|
||
color: Colors.white,
|
||
fontSize: 9,
|
||
fontWeight: FontWeight.bold,
|
||
),
|
||
),
|
||
badgeStyle: const badges.BadgeStyle(
|
||
badgeColor: CupertinoColors.systemRed,
|
||
padding: EdgeInsets.all(3),
|
||
),
|
||
position: badges.BadgePosition.topEnd(top: -4, end: -6),
|
||
child: const Icon(CupertinoIcons.sparkles),
|
||
),
|
||
activeIcon: badges.Badge(
|
||
showBadge: unreadCount > 0,
|
||
badgeContent: Text(
|
||
'$unreadCount',
|
||
style: const TextStyle(
|
||
color: Colors.white,
|
||
fontSize: 9,
|
||
fontWeight: FontWeight.bold,
|
||
),
|
||
),
|
||
badgeStyle: const badges.BadgeStyle(
|
||
badgeColor: CupertinoColors.systemRed,
|
||
padding: EdgeInsets.all(3),
|
||
),
|
||
position: badges.BadgePosition.topEnd(top: -4, end: -6),
|
||
child: const Icon(CupertinoIcons.sparkles),
|
||
),
|
||
glowColor: const Color(0xFFE8E8ED),
|
||
),
|
||
const GlassBottomBarTab(
|
||
label: '我的',
|
||
icon: Icon(CupertinoIcons.person),
|
||
activeIcon: Icon(CupertinoIcons.person_fill),
|
||
glowColor: Color(0xFFE8E8ED),
|
||
),
|
||
],
|
||
selectedIndex: currentIndex,
|
||
onTabSelected: (index) => _onTabTap(context, index),
|
||
quality: GlassQuality.premium,
|
||
selectedIconColor: ext.isDark ? Colors.white : ext.accent,
|
||
unselectedIconColor: ext.isDark
|
||
? Colors.white38
|
||
: const Color(0xFFAEAEB2),
|
||
barHeight: 56,
|
||
barBorderRadius: 28,
|
||
horizontalPadding: 16,
|
||
verticalPadding: 16,
|
||
indicatorColor:
|
||
ext.isDark
|
||
? Colors.white.withValues(alpha: 0.08)
|
||
: Colors.black.withValues(alpha: 0.04),
|
||
indicatorSettings: LiquidGlassSettings(
|
||
thickness: 40,
|
||
blur: 25,
|
||
refractiveIndex: 1.8,
|
||
chromaticAberration: 1.2,
|
||
lightIntensity: 3.5,
|
||
ambientStrength: 1.2,
|
||
glassColor:
|
||
ext.isDark
|
||
? const Color.from(alpha: 0.18, red: 1, green: 1, blue: 1)
|
||
: const Color.from(alpha: 0.12, red: 1, green: 1, blue: 1),
|
||
),
|
||
glassSettings: LiquidGlassSettings(
|
||
thickness: 30,
|
||
blur: 1.5,
|
||
refractiveIndex: 1.5,
|
||
chromaticAberration: 0.8,
|
||
lightIntensity: 1.2,
|
||
saturation: 1.0,
|
||
ambientStrength: 0.6,
|
||
glassColor:
|
||
ext.isDark
|
||
? const Color.from(alpha: 0.08, red: 1, green: 1, blue: 1)
|
||
: const Color.from(alpha: 0.05, red: 1, green: 1, blue: 1),
|
||
),
|
||
magnification: 1.12,
|
||
innerBlur: 1.5,
|
||
glowOpacity: 0.4,
|
||
glowBlurRadius: 24,
|
||
glowSpreadRadius: 4,
|
||
),
|
||
),
|
||
),
|
||
),
|
||
);
|
||
}
|
||
|
||
void _onTabTap(BuildContext context, int index) {
|
||
child.goBranch(index, initialLocation: index == child.currentIndex);
|
||
}
|
||
}
|