feat: 闲言APP v0.9.1 — 编辑器全面重写 + 迷你编辑器

- 标准编辑器: freezed数据模型 + 5Tab工具栏 + 多图层管理 + 文字增强 + 背景系统 + 导出链路
- 迷你编辑器: 极简6项功能(文字/字号/颜色/背景/预览/导出) + 三种调用方式(全屏/半屏/内嵌)
- 共享组件: GlassSlider/ColorPicker/FontPicker/TipsView
- 服务层: ExportService/ImageImportService/FontService/XycardService
- 设计系统: 统一主题令牌 + Liquid Glass风格
This commit is contained in:
Developer
2026-04-20 07:48:07 +08:00
commit 35202b51e8
461 changed files with 39318 additions and 0 deletions

View File

@@ -0,0 +1,129 @@
/// ============================================================
/// 闲言APP — 应用布局壳
/// 创建时间: 2026-04-20
/// 更新时间: 2026-04-20
/// 作用: ShellRoute 布局壳,包含底部 GlassBottomBar 导航
/// 上次更新: 替换自制 _GlassTabBar → GlassBottomBar 液态玻璃
/// ============================================================
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
import 'package:liquid_glass_widgets/liquid_glass_widgets.dart';
import '../theme/app_theme.dart';
import '../theme/app_colors.dart';
import '../router/app_router.dart';
import '../utils/interaction_animations.dart';
/// 应用布局壳
///
/// 包含底部 GlassBottomBar 液态玻璃导航的 Shell 壳,
/// 所有 Tab 页面在此容器内切换。
class AppShell extends StatelessWidget {
const AppShell({super.key, required this.child});
final Widget child;
@override
Widget build(BuildContext context) {
final ext = AppTheme.ext(context);
final String location = GoRouterState.of(context).uri.path;
final int currentIndex = _currentIndex(location);
return CelebrationOverlay(
child: Scaffold(
extendBody: true,
body: child,
bottomNavigationBar: GlassBottomBar(
tabs: const [
GlassBottomBarTab(
label: '首页',
icon: Icon(CupertinoIcons.house),
activeIcon: Icon(CupertinoIcons.house_fill),
glowColor: LightColors.primary,
),
GlassBottomBarTab(
label: '灵感',
icon: Icon(CupertinoIcons.sparkles),
activeIcon: Icon(CupertinoIcons.sparkles),
glowColor: Color(0xFFAF52DE),
),
GlassBottomBarTab(
label: '我的',
icon: Icon(CupertinoIcons.person),
activeIcon: Icon(CupertinoIcons.person_fill),
glowColor: Color(0xFF30D158),
),
],
selectedIndex: currentIndex,
onTabSelected: (index) => _onTabTap(context, index),
quality: GlassQuality.premium,
selectedIconColor: ext.isDark ? Colors.white : LightColors.primary,
unselectedIconColor: ext.isDark
? Colors.white38
: const Color(0xFFAEAEB2), // 未选中图标: 暗白38% / 浅灰
iconSize: 24, // 图标尺寸
labelFontSize: 11, // 标签字号
barHeight: 56, // 底栏高度
barBorderRadius: 28, // 底栏圆角 (药丸形)
horizontalPadding: 16, // 水平内边距
verticalPadding: 16, // 垂直内边距
showIndicator: true, // 显示选中指示器
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, // 光照强度 → 边缘高光亮度
saturation: 1.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),
),
maskingQuality: MaskingQuality.high, // 掩膜质量: 高 (双层渲染)
magnification: 1.12, // 选中放大倍率 → 透镜感
innerBlur: 1.5, // 选中内容内模糊 → 磨砂质感
glowOpacity: 0.4, // 发光透明度 → 选中光晕
glowBlurRadius: 24, // 发光模糊半径 → 光晕扩散
glowSpreadRadius: 4, // 发光扩散半径 → 光晕范围
),
),
);
}
int _currentIndex(String location) {
if (location.startsWith(AppRoutes.inspiration)) return 1;
if (location.startsWith(AppRoutes.profile)) return 2;
return 0;
}
void _onTabTap(BuildContext context, int index) {
final routes = [AppRoutes.home, AppRoutes.inspiration, AppRoutes.profile];
context.go(routes[index]);
}
}