Files
xianyan/CHANGELOG.md
Developer 93d580fa1e feat(macos): 实现 macOS 系统菜单栏多语言支持与闪退修复
本次提交完成 macOS 端多项关键优化与修复:
1. 修复启动期竞态闪退问题,通过前移窗口属性初始化、串行化特效调用、跳过首次同步实现稳定启动
2. 实现系统菜单栏多语言本地化,支持中英日韩繁五种语言,软件内切换语言可同步更新菜单栏
3. 移除视图菜单中重复的全屏按钮,统一窗口标题栏逻辑
4. 新增 macOS App Store 打包配置与本地化资源
2026-06-24 08:35:08 +08:00

1278 lines
85 KiB
Markdown
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.
# Changelog
所有重要变更均记录于此文件。格式基于 [Keep a Changelog](https://keepachangelog.com/zh-CN/)。
> 保留最近 14 个版本v6.101.0 ~ v6.120.0。更早版本v6.87.0 ~ v6.100.0)的特性已合并进软件特性功能文档,详见文末归档概览。
***
## [v6.121.0] - 2026-06-24
### 🐛 修复macOS 启动期闪退)
#### 闪退根因分析
- **Issue**: macOS 端启动后 3.5 秒闪退,崩溃栈与 v6.119.0 修复前完全一致
- **崩溃栈**:
- Thread 0 (main): `macos_window_utils``[NSWindow setBackgroundColor:]``NSThemeFrame._updateBackdropView``-[NSView removeFromSuperview]`
- Thread 8 (io.flutter.raster): `impeller::Canvas::SetupRenderPass()``KERN_INVALID_ADDRESS at 0x0`
- **根因**:
- `macos_window_utils` 插件的 `MainFlutterWindowManipulator.start()` 方法内部会调用 `showTitle()` / `makeTitlebarOpaque()` / `disableFullSizeContentView()` / `setWindowBackgroundColorToDefaultColor()` 四个方法
- `setWindowBackgroundColorToDefaultColor()` 会触发 `[NSWindow setBackgroundColor:]``NSThemeFrame._updateBackdropView``removeFromSuperview`
- Dart 侧 `WindowManipulator.initialize()` → 原生 `reset()` → 当 `mainFlutterWindow == nil` 时走 `start(nil)` 分支 → 触发上述竞态
- v6.119.0 的修复仅跳过了 Dart 侧 `applyEffect` 中的冗余调用,但**未跳过** `WindowManipulator.initialize()` 内部的 `reset()``start(nil)` 路径
- **修复**:
1.`MainFlutterWindow.awakeFromNib` 中提前调用 `MainFlutterWindowManipulator.start(mainFlutterWindow: self)`,让 `mainFlutterWindow` 静态属性先被设置
2. 之后 `WindowManipulator.initialize()``reset()` 会因 `mainFlutterWindow != nil``passthroughViewHandler.start()` 分支,不再触发 `setWindowBackgroundColorToDefaultColor()`
3. `start()` 会覆盖 `awakeFromNib` 预设的透明属性,因此在 `start()` 之后重新设置(此时 Flutter 引擎未启动Impeller raster 线程未运行,无竞态风险)
- **涉及文件**:
- `macos/Runner/MainFlutterWindow.swift` — 导入 `macos_window_utils`,提前调用 `start`,之后重新设置透明属性
### 🎨 优化macOS 窗口标题栏 + 系统菜单栏)
#### 1. macOS 系统菜单栏支持多语言
- **Issue**: macOS 系统菜单栏(应用菜单/编辑菜单/视图菜单/窗口菜单/帮助菜单)项目仅显示英文,未跟随系统语言
- **根因**:
- `MainMenu.xib` 只有 `Base.lproj` 版本,无本地化 `.strings` 文件
- `project.pbxproj``knownRegions` 仅包含 `en``Base`
- **修复**:
1. **创建本地化文件**:为 5 种主要语言创建 `MainMenu.strings`
- `en.lproj/MainMenu.strings` — 英语
- `zh-Hans.lproj/MainMenu.strings` — 简体中文
- `zh-Hant.lproj/MainMenu.strings` — 繁体中文
- `ja.lproj/MainMenu.strings` — 日语
- `ko.lproj/MainMenu.strings` — 韩语
2. **项目配置**`project.pbxproj`
- `knownRegions` 添加 `zh-Hans`/`zh-Hant`/`ja`/`ko`
- 创建 `MainMenu.strings``PBXVariantGroup``PBXFileReference`
-`MainMenu.strings` 添加到 `PBXResourcesBuildPhase`
- **效果**: 系统菜单栏跟随 macOS 系统语言显示对应文案
- **涉及文件**:
- `macos/Runner/en.lproj/MainMenu.strings` — 新增
- `macos/Runner/zh-Hans.lproj/MainMenu.strings` — 新增
- `macos/Runner/zh-Hant.lproj/MainMenu.strings` — 新增
- `macos/Runner/ja.lproj/MainMenu.strings` — 新增
- `macos/Runner/ko.lproj/MainMenu.strings` — 新增
- `macos/Runner.xcodeproj/project.pbxproj` — 添加本地化支持
#### 2. 去掉视图菜单下的 "Enter Full Screen" 按钮
- **Issue**: macOS 系统菜单栏 → 视图菜单下有 "Enter Full Screen" 按钮,与 Flutter 侧自绘的绿灯按钮(弹 window size dialog功能重复
- **修复**: 删除 `MainMenu.xib` 中 View 菜单下的 "Enter Full Screen" 菜单项
- **涉及文件**:
- `macos/Runner/Base.lproj/MainMenu.xib` — 删除 "Enter Full Screen" 菜单项
#### 3. 软件内切换语言后 macOS 系统菜单栏同步更新
- **Issue**: 软件内切换语言后macOS 系统菜单栏( 右边的按钮:应用菜单/编辑菜单/视图菜单/窗口菜单/帮助菜单)未跟随切换,仍显示原语言
- **根因**:
- macOS 启动时根据系统语言偏好加载 `MainMenu.strings`,软件内切换语言仅更新 Flutter 侧 UI未通知原生侧重新加载菜单标题
- `generalSettingsProvider.setLanguage` 方法只更新内存状态 + 持久化 KvStorage + 写日志,未调用任何 MethodChannel
- XIB 加载后 `NSMenuItem.identifier` 默认为 nil无法通过 XIB objectId 直接定位菜单项
- **修复**(三层联动):
1. **原生侧 — 建立 objectId ↔ menuItem 映射**`MainFlutterWindow.swift`
- 新增 `menuItemIds` 静态数组,按深度优先顺序记录 XIB 中所有 menuItem 的 objectId`MainMenu.xib` 声明顺序一致,跳过 separatorItem
- 新增 `assignMenuItemIdentifiers()` 方法,在 `awakeFromNib` 中递归遍历 `NSApp.mainMenu`,按顺序将 objectId 赋值给对应 `menuItem.identifier`
2. **原生侧 — 切换菜单语言**`MainFlutterWindow.swift`
- 新增 `setMenuLanguage(languageId:)` 方法:
- 根据 languageId 解析 lproj 目录名(`system``Bundle.preferredLocalizations(from:)` 跟随系统;`zh-CN`/`zh-Hans``zh-Hans``zh-TW`/`zh-Hant``zh-Hant``en`/`ja`/`ko` → 对应 lproj
- 通过 `Bundle.main.path(forResource:ofType:forLocalization:)` 加载对应语言的 `MainMenu.strings``[String: String]`
- 递归遍历 `NSApp.mainMenu`,根据 `menuItem.identifier`XIB objectId查找 `.strings` 中的 key`"id.title"`)并更新标题
- 替换 `APP_NAME` 占位符为应用名(`CFBundleName`
- MethodChannel 新增 `case "setMenuLanguage"` 处理,调用 `self.setMenuLanguage(languageId:)`
3. **Dart 侧 — 通知原生侧切换**
- `MacosPlatformService.setMenuLanguage(String languageId)` — 新增静态方法,通过 `apps.xy.xianyan/macos` 通道调用原生侧
- `generalSettingsProvider.setLanguage` — 在更新状态后调用 `MacosPlatformService.setMenuLanguage(id)`
- `DesktopServicesManager._initMenuLanguage` — 新增方法应用启动时根据用户设置的语言同步菜单栏macOS 启动时按系统语言加载 `.strings`,需根据用户设置覆盖)
- **效果**:
- 软件内切换语言后,系统菜单栏所有菜单项标题立即更新为目标语言
- 应用启动时菜单栏语言与用户设置一致(而非跟随系统语言)
- **涉及文件**:
- `macos/Runner/MainFlutterWindow.swift` — 新增 `menuItemIds`/`assignMenuItemIdentifiers`/`setMenuLanguage`awakeFromNib 调用 `assignMenuItemIdentifiers`
- `lib/core/services/device/macos_platform_service.dart` — 新增 `setMenuLanguage` 静态方法
- `lib/features/settings/providers/general_settings_provider.dart``setLanguage` 调用 `MacosPlatformService.setMenuLanguage`
- `lib/app/services/desktop_services_manager.dart` — 新增 `_initMenuLanguage`,启动时同步菜单栏语言
### 📦 打包macOS App Store 提交包重新打包)
#### 1. 生成 App Store 提交用 pkgx86_64 + arm64 通用二进制)
- **背景**: v6.121.0 修复完成后需重新打包提交 App Store
- **流程**:
1. `flutter clean` + `flutter pub get` + `pod install`
2. `flutter build macos --release` — 构建 universal binary (x86_64 + arm64)201.0MB
3. `xcodebuild archive` — 生成 xcarchiveAutomatic 签名Apple Development 证书)
4. `xcodebuild -exportArchive` — 导出 App Store pkg使用 Apple Distribution 证书重新签名
- **产物**:
- `build/Runner.xcarchive` — 归档文件
- `build/Runner/闲言.pkg` — 110MBApp Store 提交包
- **验证**:
- 主可执行文件universal (x86_64 + arm64)
- pkg 签名3rd Party Mac Developer Installer: li zhenyang (5V9NVUU6K5)
- app 签名Apple Distribution: li zhenyang (5V9NVUU6K5)
- Info.plist 包含 `ITSAppUsesNonExemptEncryption=false` 加密合规声明
- **新增文件**:
- `macos/ExportOptions.plist` — App Store 导出配置method=app-store, teamID=5V9NVUU6K5
- **上传方式**: 通过 Xcode Organizer 手动上传(`open -a Xcode-beta build/Runner.xcarchive` → Distribute App → App Store Connect → Upload
- **注意事项**:
- Release 配置保持 `CODE_SIGN_IDENTITY = "Apple Development"` + `CODE_SIGN_STYLE = Automatic`exportArchive 阶段会自动使用 Apple Distribution 证书重新签名
- 若直接将 CODE_SIGN_IDENTITY 改为 "Apple Distribution" 会与 Automatic 签名冲突,导致构建失败
---
## [v6.120.0] - 2026-06-24
### 📦 打包macOS Universal Binary 提交 App Store
#### 1. macOS 包支持 x86_64 + arm64 双架构,用于 App Store 提交
- **Issue**: 原 macOS Release 配置强制 `ARCHS = arm64`,仅生成 arm64 单架构包x86_64 Mac 无法原生运行;且 Flutter SDK `xcode_backend.dart` 中存在强制 arm64 的"修复"代码,阻止 universal binary 构建
- **根因**:
- `macos/Runner.xcodeproj/project.pbxproj` Release 配置中 `ARCHS = arm64` 限制只构建 arm64
- Flutter SDK `packages/flutter_tools/bin/xcode_backend.dart` 第 646-648 行:当 `ARCHS` 包含空格(多架构)时强制改为 `arm64`,导致 `flutter assemble` 只生成 arm64 的 FlutterMacOS.framework
- Flutter SDK `flutter_tools.snapshot` 未包含 `darwin.dart``thinFramework` 的逐架构验证修复snapshot 未随源码更新重新编译)
- **修复**:
1. **项目配置**`macos/Runner.xcodeproj/project.pbxproj`Release 配置 `ARCHS``arm64` 改为 `$(ARCHS_STANDARD)`,支持 universal binary
2. **Flutter SDK 修复**`packages/flutter_tools/bin/xcode_backend.dart`):移除 `if (platform == TargetPlatform.macos && archs.contains(' ')) archs = 'arm64'` 强制 arm64 逻辑,保留多架构传入 `flutter assemble`
3. **Snapshot 重建**:修改 `bin/cache/flutter_tools.stamp` 触发 `flutter_tools.snapshot` 重新编译,使 `darwin.dart` 的逐架构 `lipo -verify_arch` 验证修复生效
- **构建结果**:
- `build/macos/Build/Products/Release/xianyan.app` — universal (x86_64 + arm64)200.9MB
- `build/xianyan.xcarchive` — universal archive用 Apple Distribution 证书签名
- `build/pkg/闲言.pkg` — 110MB用 3rd Party Mac Developer Installer 证书签名
- **验证**:
- 主可执行文件、FlutterMacOS.framework、App.framework 均为 universal (x86_64 + arm64)
- 签名正确TeamIdentifier=5V9NVUU6K5Format=app bundle with Mach-O universal
- Info.plist 包含 `ITSAppUsesNonExemptEncryption=false` 加密合规声明
- **上传方式**: 通过 Xcode Organizer 手动上传open build/xianyan.xcarchive → Distribute App → App Store Connect → Upload
- **涉及文件**:
- `macos/Runner.xcodeproj/project.pbxproj` — Release 配置 ARCHS 改为 universal
- Flutter SDK `packages/flutter_tools/bin/xcode_backend.dart` — 移除强制 arm64 逻辑SDK 本地修改)
- Flutter SDK `bin/cache/flutter_tools.stamp` — 触发 snapshot 重建
- **注意事项**:
- Flutter SDK 的 `xcode_backend.dart` 修改是本地的,`flutter upgrade` 或重新安装 Flutter SDK 后需重新应用
- 后续 macOS App Store 打包可直接执行 `flutter build macos --release` + `xcodebuild archive` + `xcodebuild -exportArchive`
---
## [v6.119.0] - 2026-06-24
### 🐛 修复macOS Release 模式启动闪退)
#### 1. macOS Release 模式启动 ~3.5 秒后 EXC_BAD_ACCESS 空指针崩溃
- **Issue**: macOS Release 模式启动后约 3.5 秒闪退Debug 模式正常
- **崩溃栈**:
- Thread 8 (io.flutter.raster): `impeller::Canvas::SetupRenderPass()` (canvas.cc:1344) — `KERN_INVALID_ADDRESS at 0x0`
- Thread 0 (main): `macos_window_utils``[NSWindow setBackgroundColor:]``NSThemeFrame _updateBackdropView``-[NSView removeFromSuperview]`
- **根因**: 启动期 `applyEffect()` 通过 PostFrame 回调调用 `setWindowBackgroundColorToClear()`,触发 `[NSWindow setBackgroundColor:]` 修改视图层级(`removeFromSuperview`),与 Impeller raster 线程的 `SetupRenderPass` 产生竞态。Release 模式时序更紧凑竞态更易触发Debug 模式有 JIT 开销,时序较松散故未复现
- **修复**(四层防御):
1. **原生侧前移不变属性**`MainFlutterWindow.awakeFromNib`):在 Flutter 引擎启动前预设 `isOpaque=false` + `backgroundColor=NSColor.clear` + `titlebarAppearsTransparent=true` + `titleVisibility=.hidden` + `fullSizeContentView`,消除渲染期 `setBackgroundColor:` 调用
2. **Dart 侧跳过冗余调用**`MacosWindowEffectService.applyEffect`):移除 `makeTitlebarTransparent()` / `enableFullSizeContentView()` / `hideTitle()` / `setWindowBackgroundColorToClear()` 四个已在 awakeFromNib 设置的调用,仅保留主题相关的 `overrideMacOSBrightness``NSVisualEffectView` 操作
3. **互斥锁串行化**`MacosWindowEffectService`):添加 `Completer<void>` 互斥锁,防止 `applyEffect()` 并发执行导致原生视图层级竞争
4. **延迟首次应用**`DesktopServicesManager._initWindowEffect`):首次 `applyEffect()` 延迟 500ms等待 Impeller 完成初始渲染
5. **跳过首次主题同步**`ThemeSyncService.syncThemeToDesktop`):首次 build 的窗口特效同步由 `_initWindowEffect` 统一处理,避免 build() 与 PostFrame 回调并发触发 `applyEffect()`
- **涉及文件**:
- `macos/Runner/MainFlutterWindow.swift` — awakeFromNib 中预设窗口透明属性
- `lib/core/services/desktop/implementations/macos_window_effect_service.dart` — 互斥锁 + 跳过冗余调用
- `lib/app/services/desktop_services_manager.dart` — 延迟首次 applyEffect
- `lib/app/services/theme_sync_service.dart` — 跳过首次窗口特效同步
---
## [v6.118.0] - 2026-06-24
### 🐛 修复macOS 全屏退出后窗口背景变黑)
#### 1. macOS 原生全屏退出后窗口背景显示黑色而非桌面
- **Issue**: 通过「视图 → Enter Full Screen」进入原生全屏后点击绿灯退出全屏选择小窗窗口缩小后背景变为黑色无法透过窗口看到桌面
- **原因**:
- `MacosWindowEffectService.applyEffect()` 调用 `WindowManipulator.setWindowBackgroundColorToClear()` 设置了 `isOpaque=false` + `backgroundColor=NSColor.clear`
- 但全屏模式下 macOS **强制**窗口不透明(`isOpaque=true`, `backgroundColor=黑色`
- 退出全屏后这些属性未自动恢复,导致窗口背景保持黑色
- 同时 `titlebarAppearsTransparent` 也可能被系统重置
- **修复**:
- **原生侧**`MainFlutterWindow.swift`):监听 `NSWindow.didExitFullScreenNotification`,全屏退出后立即重新设置 `isOpaque=false` + `backgroundColor=NSColor.clear` + `titlebarAppearsTransparent=true`,并触发窗口重绘
- **Dart 侧**`MacosPlatformService`):新增 `initEventListeners()``onFullScreenExited` 回调,接收原生侧的全屏退出事件
- **服务层**`DesktopServicesManager`):注册全屏退出回调,退出后重新调用 `applyEffect()` 恢复完整窗口特效NSVisualEffectView 毛玻璃、标题栏融合等)
- **涉及文件**:
- `macos/Runner/MainFlutterWindow.swift` — 添加全屏退出通知监听 + `handleFullScreenExit` 方法
- `lib/core/services/device/macos_platform_service.dart` — 新增原生事件监听机制
- `lib/app/services/desktop_services_manager.dart` — 注册全屏退出回调 + 重新应用特效
---
## [v6.117.0] - 2026-06-24
### 🐛 修复macOS 菜单栏打开页面绕过工作台模式)
#### 1. macOS 顶部「闲言」菜单项打开页面不符合工作台模式且无法返回
- **Issue**: macOS 端通过系统顶部菜单栏  右侧的「闲言/文件/视图/帮助」菜单选项打开页面时,页面全屏覆盖整个窗口,不符合工作台模式布局,且无法返回上一页
- **原因**: `MacosMenuBarWrapper._navigateTo` 直接调用 `appRouter.push(route)`,将页面 push 到根 GoRouter Navigator绕过了工作台模式的右栏嵌套 Navigator导致页面独占窗口
- **修复**:
- 参考 `DesktopTrayController._navigateTo` 的修复7.1方案,改为工作台模式感知导航
- 直接读取 `splitViewProvider.workbenchEnabled` 判断工作台模式(不依赖 MediaQuery避免窗口状态切换时尺寸未就绪导致判断失败
- 工作台模式开启且非全屏路由时push 到右栏嵌套 Navigator`rightPanelStackProvider`),页面显示在右栏并支持栈式返回
- 非工作台模式或全屏路由仍走 GoRouter push
- **涉及文件**: `lib/features/desktop/macos_menu_bar_wrapper.dart`
### 🔒 合规App Store 加密出口合规声明)
#### 1. macOS Info.plist 补充加密出口合规声明
- **Issue**: App Store Connect 上传构建版本时提示「你的 App 采用了哪种类型的加密算法?」合规问卷
- **原因**: macOS 端 `Info.plist` 缺少 `ITSAppUsesNonExemptEncryption` 声明iOS 端已有)
- **修复**: 在 `macos/Runner/Info.plist` 中添加 `ITSAppUsesNonExemptEncryption = false`,声明 App 仅使用 Apple 操作系统提供的标准加密HTTPS/TLS不使用非豁免加密跳过每次上传的出口合规问卷
- **涉及文件**: `macos/Runner/Info.plist`
---
## [v6.116.0] - 2026-06-24
### 🐛 修复(情景诗词发送无回复 + 卡片堆积)
#### 1. 情景诗词发送预选词后无诗词回复
- **Issue**: 输入预选词发送后,页面没有回复诗词
- **原因**:
- `_buildMessages``poetrySessions` 历史列表构建消息,发送后新诗词未正确显示
- `_send` 方法 `isExactTag` 检查过于严格,输入同义词(如"下雨")无法触发发送
- 缺少用户消息反馈,发送后无视觉提示
- **修复**:
- 重构 `_buildMessages`:直接从 `state.jinrishiciContent` 构建当前诗词消息,不再遍历历史 sessions
- 新增 `state.currentTag` 字段追踪当前预选词,发送后显示用户消息气泡
- `_send` 方法支持同义词自动映射(如"下雨"→"雨")和单匹配自动发送
- 添加 API 错误提示(聊天中显示 ⚠️ 错误信息)
- `_selectSuggestion` 统一使用 `_doSend` 方法
- **涉及文件**: `weather_page.dart`, `weather_provider.dart`
#### 2. 情景诗词无限下滑显示多个相关诗词气泡卡片
- **Issue**: 发现页面 → 情景诗词一直下滑,出现无数个「相关诗词」气泡卡片
- **原因**: `_buildMessages` 循环为每个历史 session 都添加诗词卡片,历史 session 越多卡片越多
- **修复**: 仅显示最新 session 的诗词内容,发送一个预选词回应一首诗词,历史 session 不再展示
- **涉及文件**: `lib/features/weather/presentation/weather_page.dart`
#### 3. 情景诗词收藏/分享按钮点击无反应
- **Issue**: 相关诗词卡片中的收藏和分享按钮点击无任何响应
- **原因**: `_buildActionChip``GestureDetector` 缺少 `onTap` 回调,仅有 UI 渲染
- **修复**:
- `_buildActionChip` 新增 `onTap` 可选回调参数,点击时触发触感反馈
- 新增 `_favoritePoetry` 方法收藏诗词到本地数据库AppDatabase支持切换收藏状态
- 新增 `_sharePoetry` 方法:调用 `ShareSheet` 弹出分享面板
- **涉及文件**: `lib/features/weather/presentation/weather_page.dart`
---
## [v6.115.0] - 2026-06-24
### 🐛 修复(布局溢出)
#### 1. 拾光栏设置面板工作台模式底部溢出 143px
- **Issue**: 工作台模式右栏打开「拾光栏设置」时,内容区超出可用高度导致底部溢出 143 像素
- **原因**: `DateConfigSheet` 使用固定 `maxHeight` 约束 + 不可滚动的 `Column` 布局右栏高度扣除48px顶栏不足时溢出
- **修复**:
- 顶栏(拖拽指示器 + 关闭按钮 + 标题行)保持固定
- 内容区角色卡片、日期行、显示项、轮播开关、Tips等改为 `Expanded` + `SingleChildScrollView` 可滚动布局
- 同时修复了 `onTap` 回调的箭头函数语法问题(改为块体语法避免解析异常)
- **涉及文件**: `lib/features/home/presentation/date_config_sheet.dart`
---
## [v6.114.0] - 2026-06-23
### ✨ 增强(热力图重绘 + 智能预加载 + 动画系统 + 导航增强)
#### 1. 热力图年报水平滚动 + peakDay展示 + 月份标签 + 暗色模式
- **Issue**: 年报365天时单元格被压缩到8px下限太小难以点击peakDay已计算未展示日期范围无月份分隔暗色模式对比度过高
- **修复**:
- 年报模式cellWidth<12px使用 `SingleChildScrollView` 水平滚动固定单元格14px
- 新增 peakDay chip显示最活跃日期M月D日格式
- 新增月份标签行:自动检测月份变化点,标签与热力图周列对齐
- 暗色模式 `_levelColor` alpha降低1-4级分别 0.15/0.3/0.5/0.8
- **涉及文件**: `lib/features/reading_report/presentation/reading_report_widgets.dart`
#### 2. appPushWidget 支持 extra 参数
- **Issue**: `appPushWidget` 仅支持 builder 模式,不支持 extra 参数传递
- **修复**: 新增 `Object? extra` 可选参数,工作台模式下传入 `RightPanelEntry`
- **涉及文件**: `lib/core/router/app_nav_extension.dart`
#### 3. 句子广场智能预加载
- **Issue**: 预加载阈值固定16快速滚动时加载不及时
- **修复**: 根据滚动速度items/second动态调整阈值快速滚动(>3 items/s)时阈值翻倍上限40慢速滚动(<1 items/s)时恢复默认16
- **涉及文件**: `lib/features/home/providers/home_provider.dart`
#### 4. Beta水印屏幕尺寸动态密度
- **Issue**: 水印组数密度系数固定1.5,不同屏幕宽高比密度不一致
- **修复**: 根据屏幕宽高比动态调整密度系数:超宽屏(>1.8)用1.8,竖屏(<0.75)用1.2标准屏1.5
- **涉及文件**: `lib/shared/widgets/beta_testing_overlay.dart`
#### 5. 动画强度感知 — 仅首次入场动画开关
- **Issue**: 用户设置"无动画"后入场动画仍播放
- **修复**: 入场动画读取 `themeSettingsProvider.animationIntensity``durationMultiplier<=0` 时跳过动画,其他强度按倍率调整时长和曲线
- **涉及文件**: `lib/features/home/presentation/widgets/home_sentence_list_section.dart`
#### 6. 句子卡片退出动画 + 列表项删除动画
- **Issue**: 屏蔽内容时卡片直接消失,无过渡动画
- **修复**:
- `HomeState` 新增 `exitingIds` 字段标记退出中的卡片
- `blockContent` 先标记退出中延迟300ms后从列表移除
- 退出动画fadeOut + slideX(0→0.3) + scale(1.0→0.9)
- **涉及文件**: `lib/features/home/providers/home_state.dart``lib/features/home/providers/home_interaction_mixin.dart``lib/features/home/presentation/widgets/home_sentence_list_section.dart`
#### 7. 创作卡片/编辑此句返回主页动画
- **Issue**: 从编辑器返回主页时无重新聚焦动画
- **修复**: 新增 `markReturnedFromEditor()` 方法,清空入场动画历史,编辑器返回后句子卡片重新播放入场动画
- **涉及文件**: `lib/features/home/providers/home_provider.dart``lib/features/home/presentation/providers/sentence_detail_sheet.dart``lib/features/home/presentation/panels/sentence_detail_actions.dart`
***
## [v6.113.0] - 2026-06-23
### 🐛 修复(句子广场循环加载 + 热力图重绘 + 入场动画增强)
#### 1. 句子广场骨架卡死修复任务6
- **Issue**: 主页句子广场滑到底部时显示骨架无法滑动,列表不增长
- **根因**: `fetchNewSentences` 去重耗尽后使用 fallback 但 `hasMore=true`,导致骨架持续显示但无新数据追加;`_buildListBottom``hasMore=false` 时返回空 `SizedBox.shrink()`
- **修复**:
- `home_feed_mixin.dart`: 去重3轮后无新数据时重置 `allSeenIds`/`allSeenTexts`保留最近20条避免立即重复用本次返回数据继续填充列表实现循环加载
- `home_sentence_list_section.dart`: `_buildListBottom``hasMore=false` 且非离线时,显示"已经看完所有内容"提示 + 重新加载按钮(带入场动画)
- 新增 `resetAndReload()` 方法清空已见集合从第1页重新拉取
- **涉及文件**: `lib/features/home/providers/home_feed_mixin.dart``lib/features/home/providers/home_provider.dart``lib/features/home/presentation/widgets/home_sentence_list_section.dart``lib/features/home/presentation/home_page.dart`
#### 2. 句子卡片入场动画增强任务6.1
- **Issue**: 句子载入时入场动画较单一(仅 fadeIn + slideY
- **修复**:
- 增强 `_SentenceCardWithSkeleton` 入场动画fadeIn + slideY(0.15) + scale(0.95→1.0, easeOutBack) + blur(4px→0, 聚焦效果) + shimmer(accent色微妙高光)
- 错峰延迟从 50ms 提升到 60ms最多 12 个卡片参与级联
- 骨架屏 `_LoadingSkeletonCard` 增加 fadeIn + scale 入场动画
- **涉及文件**: `lib/features/home/presentation/widgets/home_sentence_list_section.dart`
#### 3. 使用报告活跃热力图重绘任务7
- **Issue**: 热力图卡片左边是热力图,右边空白,未铺满卡片
- **修复**:
- 使用 `LayoutBuilder` 响应式计算单元格尺寸,`Expanded` 铺满卡片宽度
- 新增统计 chip 行:连续活跃天数、活跃天数/总天数、活跃率百分比
- 新增图例行:"活跃度分布" 标签 + 少→多 渐变图例
- 新增日期范围标注:底部显示起止日期(月.日格式)
- 单元格尺寸根据周数动态计算clamp 8-18px高度略大于宽度
- **涉及文件**: `lib/features/reading_report/presentation/reading_report_widgets.dart`
***
## [v6.112.0] - 2026-06-23
### ♻️ 重构emoji完全迁移 + 窗口控制去重 + 鸿蒙端冗余简化)
#### 1. _CloseActionTile 的 actionEmoji 迁移到 CupertinoIcons任务10扩展
- **Issue**: _CloseActionTile 的 actionEmoji 仍使用 emoji🔴🟡❓与任务8的 emoji→icon 迁移不一致
- **修复**:
- actionEmoji 从字符串 emoji 改为 IconDataCupertinoIcons.xmark_circle_fill/minus_circle_fill/question_circle_fill
- 图标颜色使用语义色:关闭=errorColor、最小化=warningColor、询问=textHint
- 描述文本和分段控件子项改为 Row(Icon + Text) 布局
- optionText 函数移除 emoji改为纯文本Semantics value 应为描述性文本)
- **涉及文件**: `lib/features/settings/presentation/workbench/workbench_settings_page.dart`
#### 2. AdaptiveNavBar 水平模式移除窗口控制按钮任务10扩展
- **Issue**: floatingNavBar 为 null 时回退到 AdaptiveNavBar 水平模式,会显示 - 口 X 按钮与任务8"顶部去掉窗口按钮"要求矛盾
- **根因**: DesktopWindowTitleBar 已在顶部提供完整窗口控制macOS红黄绿灯/Windows方按钮AdaptiveNavBar 水平模式的窗口控制按钮是重复显示
- **修复**:
- 移除 _buildHorizontal 中的 `if (isTop && pu.isDesktop) _buildDesktopWindowControls(context, ext)` 条件
- 删除 _buildDesktopWindowControls 方法、_showWindowSizeMenu 方法、_WindowControlBtn 类
- 删除不再需要的 importswindow_manager/WindowCloseHandler/WindowSizePopup/platform_utils
- 删除未使用的 isRight、isTop、splitState 变量
- **涉及文件**: `lib/app/layout/adaptive_nav_bar.dart`
#### 3. 确认顶部窗口控制不缺失任务10扩展
- **Issue**: 任务8去掉顶部 - 口 X 按钮后,用户可能无法通过标准窗口控件关闭窗口
- **确认**:
- macOS 端DesktopWindowTitleBar 左侧提供红黄绿三圆点按钮(关闭/最小化/最大化),系统原生风格
- Windows 端DesktopWindowTitleBar 右侧提供方形按钮(最小化/最大化/关闭Windows 原生风格
- DesktopWindowTitleBar 在 app_shell.dart 中始终显示在桌面端顶部第78-85行窗口控制不缺失
- **涉及文件**: 无修改(确认现有实现已满足需求)
#### 4. GlassBottomBar 鸿蒙端防御性冗余简化任务10扩展
- **Issue**: floatingNavBar 构建时判断 `AppShell._isOhos && !liquidGlassReady`,但工作台模式已在 build() 中通过 `!pu.isOhos` 过滤鸿蒙端,此判断是防御性冗余
- **修复**:
- floatingNavBar 直接构建 _buildGlassBottomBar不再判断鸿蒙端
- 添加注释说明工作台模式已过滤鸿蒙端
- floatingNavBar 类型从 `Widget?` 改为 `Widget`(不再为 null
- **涉及文件**: `lib/app/layout/app_shell.dart`
***
## [v6.111.0] - 2026-06-23
### ✨ 新增与增强(情景诗词预选词 + 工作台导航栏图标化 + 滑动性能优化)
#### 1. 情景诗词发送框改为输入预选框任务5
- **Issue**: 情景诗词页面发送框可输入任意文本,与"情景关联"语义不符
- **增强**:
- 发送框改为预选词输入栏,只能发送预选的字词
- 输入时自动匹配预选词(支持同义词和拼音匹配),匹配不上时发送按钮禁用
- 发送预选词后根据预选字词调用 jinrishici API 获取对应标签的诗词
- 失焦时若仅1条建议自动填充空输入+聚焦时显示常用标签
- 记录标签使用频率用于智能排序getMostUsedTags/recordTagUsage
- **涉及文件**: `lib/features/weather/presentation/weather_page.dart``lib/features/weather/weather_provider.dart`
#### 2. 情景诗词设置城市联动 + 动态主题按钮字体不可见修复任务5.1
- **Issue**: 情景诗词设置页城市修改后页面不显示对应城市诗词;部分按钮字体色和按钮色一致导致选中时看不到字体
- **修复**:
- WeatherSettingsNotifier 持久化到 KvStorage城市修改后联动 weatherProvider.loadPoetryByTag(city)
- 新增"应用城市"按钮和 _onCityChanged 处理
- AppThemeExtension 新增 computeContrastColor 静态方法WCAG 相对亮度公式)和 computedTextOnAccent getter
- _buildSegmentedRow 选中态文字颜色从 ext.textOnAccent 改为 _computeContrastColor(ext.accent)
- 任务9审计修复原 _pow 方法对小数指数处理有 bug0.4.toInt()=0 导致循环0次返回1.0),改用 dart:math 的 pow 确保计算精度
- **涉及文件**: `lib/features/weather/presentation/weather_settings_page.dart``lib/core/theme/app_theme.dart`
#### 3. 诗词下方"第x首推荐"改为"相关诗词"只推荐一首任务5.2
- **Issue**: 诗词下方显示"第x首推荐",推荐多首诗词
- **修复**: 改为"相关诗词"标题matchedPoems 使用 .take(1) 只取1首
- **涉及文件**: `lib/features/weather/presentation/weather_page.dart`
#### 4. macOS 托盘打开页面独占窗口修复任务7.1
- **Issue**: macOS 端工作台模式从托盘打开页面时独占一个窗口,导致工作台布局失效
- **根因**: _navigateTo 方法使用 MediaQuery.sizeOf 判断工作台模式,窗口恢复时 MediaQuery 返回0导致判断失败
- **修复**: 直接读取 splitViewProvider.workbenchEnabled 判断,工作台模式时 push 到 rightPanelStackProvider完全绕过 MediaQuery
- **涉及文件**: `lib/features/desktop/desktop_tray_controller.dart`
#### 5. 托盘切换工作台/导航栏位置概率不生效修复任务7.2
- **Issue**: macOS 端从托盘点击工作台模式开启/关闭或切换导航栏位置时概率不生效
- **根因**: 未聚焦窗口 + 同步 updateMenu 与原生菜单回调冲突
- **修复**: _onToggleWorkbench 和 _onSetNavBarPosition 添加 _focusMainWindow() 调用_updateMenu 改为 Future.microtask 延迟执行
- **涉及文件**: `lib/features/desktop/desktop_tray_controller.dart`
#### 6. 导航栏位置卡片 emoji 改 icon + 顶底用 GlassBottomBar 悬浮 tap 栏任务8
- **Issue**: 导航栏位置卡片使用 emoji 不统一;顶/底 tap 栏占位而非悬浮
- **增强**:
- NavBarPosition 新增 icon 属性CupertinoIcons.arrow_left/right/up/down和 glassLabelIcon 属性top/bottom 返回 rectangle_stack
- 设置页分段控件和 Picker 弹窗从 emoji+label 改为 Row(Icon + Text)
- WorkbenchLayout 新增 floatingNavBar 参数,水平位置(顶/底)改用 Stack 布局实现悬浮不占位
- AppShell 提取 _buildGlassBottomBar 方法供窄屏布局和工作台顶/底布局复用
- 顶部去掉 - 口 X 窗口按钮,将 app 模式的 tap 栏调整到上方
- **涉及文件**: `lib/core/providers/split_view_provider.dart``lib/features/settings/presentation/workbench/workbench_settings_page.dart``lib/features/settings/presentation/general/general_settings_pickers.dart``lib/core/layout/workbench/workbench_layout.dart``lib/app/layout/app_shell.dart`
#### 7. 工作台模式句子广场滑动卡顿优化任务7
- **Issue**: 工作台模式主页句子广场滑动时卡顿不丝滑
- **优化**:
- 预加载检查onCheckPreload/onLoadMore从 Future(() => ...) 改为 WidgetsBinding.instance.addPostFrameCallback避免在 build 中触发副作用
- SliverChildBuilderDelegate 设置 addRepaintBoundaries: false已在子项手动添加 RepaintBoundary和 addAutomaticKeepAlives: false句子卡片无需保持存活状态
- LongPressDraggable 的 feedback 改为轻量占位卡片仅显示句子文本和作者childWhenDragging 改为简单图标占位符,避免构建完整 SentenceCard
- CustomScrollView 添加 cacheExtent: 800预渲染视口外的卡片减少滚动时的重建
- **涉及文件**: `lib/features/home/presentation/widgets/home_sentence_list_section.dart``lib/features/home/presentation/home_page.dart`
#### 8. 任务9审计修复weather_provider 空指针风险
- **Issue**: loadPoetryByTag 方法中 state.weather! 和 state.mood! 使用非空断言,天气未加载完成时可能抛出空指针异常
- **修复**: 直接从 jinrishiciData 提取数据,不再创建 WeatherPoetryResult 对象,避免 state.weather!/state.mood! 空指针风险
- **涉及文件**: `lib/features/weather/weather_provider.dart`
***
## [v6.110.3] - 2026-06-23
### 🐛 修复(窗口尺寸选择菜单 clamp 崩溃 + 屏幕尺寸获取不可靠)
#### 1. WindowSizePopup 选择尺寸时 clamp 抛出 Invalid argument(s): 360.0(严重)
- **Issue**: macOS 端点击窗口栏绿灯按钮,选择窗口尺寸预设时抛出 `Invalid argument(s): 360.0`,菜单无法应用尺寸
- **根因**:
- `_applySize``targetH.clamp(minH, screen.height - 16)` 要求 `lowerLimit <= upperLimit`
-`_screenWorkArea` 异步初始化未完成时,回退到 `MediaQuery.sizeOf(context)`,而 MediaQuery 在桌面端返回的是**窗口尺寸**(可能很小,如 300×200
-`screen.height - 16 < 360`(即窗口高度 < 376`clamp(360.0, <360)` 抛出 `Invalid argument(s): 360.0`
- **修复**:
- 使用 `math.max(minW, screen.width - 16)` 确保 clamp 上限不小于下限
- `_applySize` 中若 `_screenWorkArea` 为 null`await _refreshScreenWorkArea()` 同步刷新一次,避免回退到窗口尺寸
- 添加安全默认值 `Size(1280, 800)` 作为最终回退
- **涉及文件**: `lib/shared/widgets/window_size_popup.dart`
#### 2. _refreshScreenWorkArea 屏幕尺寸获取不可靠
- **Issue**: `PlatformDispatcher.views.first.physicalSize` 在窗口初始化阶段可能为 `Size.zero`,导致计算出的屏幕尺寸为 0
- **根因**: Flutter 视图未完成首帧布局时 `physicalSize` 未初始化
- **修复**:
- 检测 `physical.isEmpty || dpr <= 0`,回退到 MediaQuery
- 添加防御性检查:若 workArea 为空或异常小(<100px使用安全默认值 `Size(1280, 800)`
- catch 块同样添加防御性检查
- **涉及文件**: `lib/shared/widgets/window_size_popup.dart`
***
## [v6.110.2] - 2026-06-23
### 🐛 修复(收藏页面瀑布流视图 RenderFlex 布局崩溃)
#### 1. FavoriteGridCard 在瀑布流中 Expanded 无界高度约束崩溃(严重)
- **Issue**: macOS 运行时进入"我的收藏"页面切换到瀑布流视图MasonryGridView后抛出 `RenderFlex children have non-zero flex but incoming height constraints are unbounded`,连锁触发 `RenderBox was not laid out: RenderFlex` / `RenderPadding` / `RenderDecoratedBox` / `RenderRepaintBoundary` / `RenderSemanticsGestureHandler`,以及 `sliver_multi_box_adaptor.dart: child.hasSize` 断言失败和 `Null check operator used on a null value`,导致整个收藏页面无法渲染
- **根因**:
- `FavoriteGridCard` 同时用于网格视图(`GridView.builder` + `childAspectRatio: 0.85`,高度有界)和瀑布流视图(`MasonryGridView.count`,高度无界 0~Infinity
- `Column` 内使用 `Expanded` 包裹文本内容,`Expanded` 要求父级提供有限高度约束
- 瀑布流中父级高度约束为 `0~Infinity`(无界),`Expanded` 与 shrink-wrap 互斥,触发断言
- `Column``mainAxisSize` 默认为 `MainAxisSize.max`,在无界约束下尝试扩展到无限大小
- **修复**:
-`Expanded` 改为 `Flexible`(默认 `FlexFit.loose`),在有界约束下可扩展填充剩余空间,在无界约束下可自然收缩到子组件固有大小
- 显式设置 `Column``mainAxisSize: MainAxisSize.min`,让 Column 收缩包裹子组件,避免在无界约束下尝试扩展
- `_buildHighlightedText` 已有 `maxLines: 5` + `overflow: TextOverflow.ellipsis` 限制,可保证文本不溢出
- **涉及文件**: `lib/features/home/presentation/favorite/favorite_card.dart`
***
## [v6.110.1] - 2026-06-23
### 🐛 修复Beta 水印蒙版布局崩溃 + 情景诗词标题溢出 + 框架错误弹窗骚扰)
#### 1. BetaTestingOverlay 无限约束导致 RenderBox 布局失败(严重崩溃)
- **Issue**: macOS 运行时抛出 `BoxConstraints forces an infinite width and infinite height` + `RenderBox was not laid out: RenderTransform`,导致 4 个实验性页面(工具中心/编辑器/句子来源/桌面小部件)无法正常渲染
- **根因**:
- `OverflowBox` 使用 `maxWidth/maxHeight: double.infinity` 传播无限约束
- `Container` 设置 `width/height: double.infinity` 在无限约束下无法计算自身尺寸
- `Transform.rotate` 包裹无限大小的子组件,导致 RenderBox 无法布局
- **修复**:
- 移除 `OverflowBox``double.infinity`,改用屏幕对角线 × 1.5 作为有限容器尺寸(保证旋转后仍覆盖全屏)
- 移除 `Container``width/height: double.infinity`,改用 `Padding` 避免无限尺寸传播
- **涉及文件**: `lib/shared/widgets/beta_testing_overlay.dart`
#### 2. BetaTestingOverlay ParentData 传递失败Positioned 必须直接挂在 Stack 下)
- **Issue**: macOS 运行时抛出 `Incorrect use of ParentDataWidget``Positioned` 无法找到 `Stack` 祖先
- **根因**: `IgnorePointer` 包裹了 `Positioned.fill`,阻断了 `StackParentData` 的传递(`Positioned` 必须是 `Stack` 的直接子组件,中间不能有其他 RenderObjectWidget
- **修复**: 将 `Positioned.fill` 移到最外层作为根组件,`IgnorePointer` 放在其内部
- **涉及文件**: `lib/shared/widgets/beta_testing_overlay.dart`
#### 3. 情景诗词推荐列表标题 2 像素右侧溢出
- **Issue**: 情景诗词页面推荐 tab 中的诗词卡片元信息行(作者 + 标题 + 关键词)溢出 2 像素
- **根因**:
- 作者 `Text` 和标题 `Text` 未包裹 `Flexible`,按固有宽度渲染不收缩
- `Spacer()` 强制占用剩余空间,与未收缩的文本冲突
- 当作者名 + 《标题》+ 关键词 + 间距超过 Row 可用宽度时产生溢出
- **修复**:
- 作者和标题 `Text``Flexible` 包裹,添加 `maxLines: 1` + `overflow: TextOverflow.ellipsis`
- 移除 `Spacer()`,改用固定 `SizedBox(width: AppSpacing.sm)` 间距,避免与 `Flexible` 冲突
- **涉及文件**: `lib/features/weather/presentation/weather_page.dart`
#### 4. IOSScrollViewFlingVelocityTracker 时间戳乱序错误弹窗骚扰Flutter 框架 bug 静默处理)
- **Issue**: macOS 上滚动时偶发 `The position being added ... has a smaller timestamp ... than its predecessor` 错误,触发 Catcher2 弹窗打扰用户
- **根因**: Flutter 框架 `IOSScrollViewFlingVelocityTracker.addPosition` 断言时间戳单调递增,但 macOS/iOS 触摸事件时间戳偶尔乱序(框架已知 bug非应用代码问题
- **修复**:
- `Catcher2ConfigService`: 新增 `_silentFrameworkErrorPatterns` 统一过滤框架内部已知非致命错误
- `CopyableDialogReportMode`: 匹配静默模式时自动确认不弹窗
- `_ConsoleLogHandler`: 静默错误降级为 `Log.w`,不记录到 `CrashLogService`
- `GlobalErrorHandler`: 同步增加 `smaller timestamp` 静默处理,保持双层防护一致性
- **涉及文件**: `lib/core/services/catcher2_config_service.dart``lib/core/services/error/global_error_handler.dart`
***
## [v6.110.0] - 2026-06-23
### ✨ 新增Beta 测试全局水印蒙版 + 诗词匹配增强 + 动画可交互)
#### 1. Beta 测试全局透明水印蒙版Issue 2 Flutter 实施)
- **Issue**: 工具中心/编辑器/句子来源/桌面小部件 4 个实验性页面需添加透明网格水印蒙版,标识 Beta 测试状态与设备溯源信息
- **修改**:
- 新增 `BetaTestingOverlay` 共享组件透明网格水印3 行内容(主标识/状态提示/溯源信息),字体统一 12px斜向 -22° 排列水印贯穿两侧OverflowBox + Transform.rotate + Wrap 平铺)
- 3 行内容:① 闲言APP beta testing加粗② 实验中的功能(斜体)③ IP · 机型 · 时间 · 版本 · 随机码(等宽字体)
- 异步并行加载设备信息DeviceInfoService.getDeviceName与 IP 地址IpLocationService.queryMyIp加载完成前不显示蒙版避免闪烁
- 浅色/深色主题自适应颜色IgnorePointer 包裹不阻挡页面交互
- 偶数组额外显示 `xianyan · beta` 标识行增加视觉层次
- **水印密度动态调整**LayoutBuilder 根据屏幕尺寸计算 itemCount屏幕面积 / 单组面积 × 1.2 密度系数clamp 到 [6, 30],小屏稀疏大屏饱满
- **本地 IP 回退**三级回退策略queryMyIp 24h缓存 → KvStorage 永不过期上次IP → 未知IP离线时仍可显示上次 IP
- **涉及文件**:
- 新增 `lib/shared/widgets/beta_testing_overlay.dart`
- 修改 `lib/features/home/presentation/home_tool_center.dart`Stack 顶层叠加)
- 修改 `lib/editor/pages/editor/editor_page.dart`ProEditorPage 与加载态均叠加)
- 修改 `lib/features/source/presentation/source_page.dart`CupertinoPageScaffold 外层 Stack 叠加)
- 修改 `lib/features/widget/presentation/widget_management_page.dart`CupertinoPageScaffold 外层 Stack 叠加)
### 🐛 修复(诗词匹配精度 + API 标签限制 + 搜索历史 + 动画交互 + 功耗 tips + 去重池 + 加载动画)
#### 2. 情景诗词匹配精度有限(拼音/同义词无法匹配)
- **Issue**: `findMatchingTags` 使用 contains 模糊匹配,输入"下雨"无法匹配"雨",拼音/同义词无法匹配
- **修改**:
- 新增 60+ 条同义词/近义词映射表 `kSynonymMap`(如"下雨"→["雨"]、"南京"→["金陵"]、"梅"→["梅花"]
- 新增 3 层匹配策略:① 同义词映射 ② 中文包含匹配 ③ 拼音匹配PinyinHelper.getShortPinyin/getPinyin
- 新增拼音缓存 `_pinyinCache` 避免重复计算
- 匹配结果按使用频率智能排序(`_sortByUsageFrequency`
- **涉及文件**: `lib/features/poetry/presentation/poetry_tags.dart`
#### 3. 无搜索历史记录与智能排序
- **Issue**: 用户频繁使用的标签未记录,无智能排序
- **修改**:
- 新增 `getTagUsageHistory`/`recordTagUsage`/`getMostUsedTags` 基于 KvStorage 持久化标签使用历史
- 存储格式 `tag\u0000count`,保留前 30 条高频标签
- `PoetryInputBar` 发送/选择建议时调用 `recordTagUsage` 记录
- 输入框聚焦且为空时显示"常用"标签行(最多 6 个),点击直接发送
- **涉及文件**:
- `lib/features/poetry/presentation/poetry_tags.dart`
- `lib/features/poetry/presentation/poetry_widgets.dart`
#### 4. API 标签限制fetchSentenceByTag 重试仍可能不匹配)
- **Issue**: jinrishici API 不支持客户端传 tag 参数matchTags 重试最多 3 次仍可能不匹配
- **修改**:
- 新增内存缓存 `_tagCache`5 分钟 TTL命中缓存直接返回避免重复请求
- 重试次数从 3 次增至 5 次,每次间隔 500ms
- 第 3 次仍不匹配时再次清除 Token 换推荐种子
- 5 次都不匹配时返回最后结果并缓存(仍可展示)
- 所有请求失败时回退到无标签的 `fetchSentence()`
- **涉及文件**: `lib/core/services/data/jinrishici_sdk_service.dart`
#### 5. 动画为静态循环(无法响应用户交互)
- **Issue**: 工作台/分屏动画演示为纯演示性质,无法点击切换方向
- **修改**:
- 新增 `_paused1`/`_paused2` 状态与 `_togglePause1()`/`_togglePause2()` 方法
- 点击动画卡片切换暂停/继续,暂停时显示半透明遮罩 + play 图标
- AnimationController 通过 `stop()`/`repeat(reverse: true)` 控制暂停/继续
- **涉及文件**: `lib/features/settings/presentation/workbench/workbench_animation_demos.dart`
#### 6. 动画尺寸固定(小屏拥挤)
- **Issue**: `_AnimationCard` 高度固定 60px小屏下可能拥挤
- **修改**:
- 改用 LayoutBuilder 自适应高度:`animHeight = (maxW * 0.5).clamp(50.0, 80.0)`
- 宽度与高度均根据父容器约束动态计算
- **涉及文件**: `lib/features/settings/presentation/workbench/workbench_animation_demos.dart`
#### 7. 功耗 tips 文案单一(未区分移动端/桌面端)
- **Issue**: 功耗提示未区分移动端/桌面端的功耗差异说明
- **修改**:
- `PowerConsumptionTip` 根据 `pu.isMobile`/`pu.isDesktop` 显示不同文案
- 移动端:"移动端同时打开多个页面会增加功耗与内存占用"
- 桌面端:"桌面端多页面并行渲染会占用更多显存与 CPU 资源"
- 其他平台:"同时打开多个页面会增加系统资源占用"
- **涉及文件**: `lib/features/settings/presentation/workbench/workbench_animation_demos.dart`
#### 8. 日签去重池仅 20 条(高频换一句仍可能重复)
- **Issue**: 去重池容量仅 20 条,高频换一句后仍可能重复
- **修改**: `_maxHistorySize` 从 20 扩容至 50降低高频换一句时的重复概率
- **涉及文件**: `lib/features/daily_card/daily_card_provider.dart`
#### 9. 换一句无加载动画(内容突然替换)
- **Issue**: 换一句过程中无过渡动画,内容突然替换
- **修改**:
- AnimatedSwitcher 的 key 加入 `content.text.hashCode`,内容变化时触发过渡
- 新增 `transitionBuilder`FadeTransition + ScaleTransition0.95→1.0
- 新增 `isRefreshing` 半透明遮罩 + CupertinoActivityIndicator 居中加载指示器
- IgnorePointer 包裹遮罩避免阻挡交互
- **涉及文件**: `lib/features/daily_card/presentation/daily_card_page.dart`
***
## [v6.109.0] - 2026-06-23
### ✨ 新增(情景诗词输入预选框 + 工作台动画演示)
#### 1. 情景诗词发送框改为输入预选框
- **Issue**: 用户要求发送框只能发送预选词,输入时自动匹配预选词,根据预选词更换诗词
- **修改**:
- 新增 `PoetryInputBar` 组件:输入框+发送按钮,实时匹配预选词建议列表,仅允许发送精确匹配的预选词
- 新增 `kAllPoetryTags` 扁平化标签列表、`findMatchingTags` 模糊匹配、`isExactTag` 精确匹配辅助函数
- 增强 `fetchSentenceByTag`:增加 matchTags 匹配重试最多3次提升标签与诗词相关性
- 增强城市显示:从纯文本改为带图标的卡片样式,显示当前城市+天气+温度
- **涉及文件**:
- `lib/features/poetry/presentation/poetry_tags.dart`
- `lib/features/poetry/presentation/poetry_widgets.dart`
- `lib/features/poetry/presentation/poetry_page.dart`
- `lib/core/services/data/jinrishici_sdk_service.dart`
#### 2. 工作台模式设置页增加动画演示图
- **Issue**: 工作台模式和分屏功能开关下方需增加动画演示图,导航栏位置卡片需增加功耗提示
- **修改**:
- 新增 `WorkbenchModeAnimationDemos`工作台↔App模式切换动画三栏收缩/展开)
- 新增 `SplitViewAnimationDemos`:竖屏↔横屏切换动画(上下/左右分栏淡入淡出)
- 新增 `PowerConsumptionTip`:功耗内存占用提示标签
- `_SliderTile` 增加 `trailing` 参数支持右下角附加组件
- **涉及文件**:
- 新增 `lib/features/settings/presentation/workbench/workbench_animation_demos.dart`
- 修改 `lib/features/settings/presentation/workbench/workbench_settings_page.dart`
### 🐛 修复(窗口尺寸 + 横屏布局 + 路由匹配 + 骨架超时)
#### 3. macOS/Win窗口尺寸选择异常
- **Issue**: 12-13寸笔记本选择1920×1080后窗口比屏幕大4K/2K大显示器选择800×600后窗口很小
- **修改**:
- 将绝对像素预设改为屏幕比例预设50%/65%/75%/85%/95%/100%
- 新增 `_refreshScreenWorkArea` 检测屏幕工作区macOS扣28px菜单栏Win扣48px任务栏
- `_applySize` 按比例计算目标尺寸并 clamp 到屏幕安全区,应用后居中
- UI 显示比例标签+动态像素值+屏幕尺寸
- **涉及文件**: `lib/shared/widgets/window_size_popup.dart`
#### 4. 移动端横屏左侧空白
- **Issue**: 横屏窄屏(600<width<768)时使用 Center+ConstrainedBox 导致两侧空白
- **修改**: 改为 `Row[_buildVerticalTabBar(), Expanded(content)]` 布局左侧显示垂直tab栏
- **涉及文件**: `lib/app/layout/app_shell.dart`
#### 5. 工作台切换App模式后按钮残留选中态
- **Issue**: 从工作台模式切换成app模式后已打开页面的按钮仍显示选中着重色
- **修改**:
- `activeRightPanelRouteProvider` 增加工作台模式守卫,非工作台模式返回 null
- `RightPanelStackNotifier` 新增 `clearAll()` 方法清空所有Tab右栏栈
- `setWorkbenchEnabled` 关闭工作台模式时调用 `clearAll()`
- **涉及文件**:
- `lib/core/layout/workbench/right_panel_navigator.dart`
- `lib/core/providers/split_view_provider.dart`
#### 6. 嵌套子路由匹配失败
- **Issue**: 闲情逸致页面点击设置icon无法跳转到设置页面
- **根因**: `_findInChildren` 比较 `def.path == path`,但子路由路径是相对的(如`settings`),搜索路径是绝对的(如`/leisure/settings`
- **修改**: 新增 `_joinPath` 辅助函数拼接父路径和子路径,`_findInChildren``_findInChildrenParam` 增加 `parentPath` 命名参数
- **涉及文件**: `lib/core/router/route_registry.dart`
#### 7. 闲情逸致骨架持续显示
- **Issue**: 工作台模式下闲情逸致页面有时一直显示骨架不显示内容
- **根因**: `_init()` 中的数据加载操作没有超时保护,可能挂起导致 `isLoading` 永远为 true
- **修改**: 为每个 `loadIndex()``loadMonth()` 调用添加3秒超时`build()` 中添加5秒安全兜底强制结束 loading
- **涉及文件**: `lib/features/tool_center/leisure/providers/leisure_timeline_provider.dart`
#### 8. 日签卡片换一句无效
- **Issue**: 点击换一句后卡片内容未更换
- **根因**: `refreshCurrentType()` 优先调用 `_fetchByType`每日API同一天返回相同内容
- **修改**: 改为优先使用 `_fetchFromChannel`(带去重+重试的频道随机接口失败时回退到每日API新增内容相同检测若相同再尝试一次
- **涉及文件**: `lib/features/daily_card/daily_card_provider.dart`
#### 9. 导出个人信息页面布局错误
- **Issue**: `[ERR-MQPK2MM9]` proxy_box.dart `!debugNeedsLayout` 断言错误
- **根因**: `Flexible` + `shrinkWrap: true` ListView 在 `Column` 中导致布局问题
- **修改**: 改为 `Expanded`(移除 `shrinkWrap`),提供固定高度约束
- **附加**: 列表底部新增 tips 气泡提示URL 使用强调色可点击复制
- **涉及文件**: `lib/features/settings/presentation/account/account_export_info_sheet.dart`
### 📝 文案修改
#### 10. 了解我们页面文案更新
- "官网首页"改为"在 闲言App",增加副标题"在其他设备上下载闲言app"
- URL 改为 `https://s2ss.com/app.html`
- 团队签名更新:无书的书→"不会写代码的小书",伯乐不相马→"这个bug有力气👍"
- **涉及文件**: `lib/features/profile/presentation/learn_us_sections.dart`, `lib/features/profile/presentation/learn_us_widgets.dart`, `lib/l10n/languages/zh_cn.dart`
#### 11. 工作台模式文案更新
- "微信PC"改为"studio"
- **涉及文件**: `lib/l10n/languages/zh_cn.dart`, `lib/l10n/languages/zh_tw.dart`
### 🎨 新功能预告
#### 12. 新版本功能介绍增加预告视图
- 新增预告卡片:"下个版本即将支持在应用内加载网页url"
- **涉及文件**: `lib/features/home/presentation/widgets/new_features_dialog.dart`
***
## [v6.108.0] - 2026-06-23
### 🐛 修复(布局溢出 + 运行时错误)
#### 1. 翻译助手页面底部溢出 29px
- **Issue**: 分栏模式下空状态内容(图标+文字+快捷翻译芯片)超出可用高度导致 BOTTOM OVERFLOWED BY 29 PIXELS
- **修改**: `_buildEmptyState` 包裹 `SingleChildScrollView(physics: NeverScrollableScrollPhysics)` 允许内容在受限空间内自适应收缩
- **涉及文件**: `lib/features/discover/presentation/pages/translate/translate_page.dart`
#### 2. 情景诗词页面右侧溢出 2px
- **Issue**: 诗词卡片 padding(AppSpacing.md) + ListView 水平 padding 叠加后总宽度超出 2px
- **修改**: 卡片水平 padding 从 `AppSpacing.md`(16) 缩减为 `AppSpacing.sm`(8),垂直保持不变
- **涉及文件**: `lib/features/poetry/presentation/poetry_page.dart`
#### 3. 发现页松手打开区域底部溢出 38px
- **Issue**: 下拉刷新指示器容器使用固定 `height` 但内部内容(气泡+精灵角色+进度条)实际高度超出容器
- **修改**: 容器从固定 `height` 改为 `constraints: BoxConstraints(minHeight:)`,允许内容撑开
- **涉及文件**: `lib/features/discover/presentation/pages/home/discover_page.dart`
#### 4. Quick Card 编辑器右侧溢出
- **Issue**: 预览区宽度计算 `screenWidth - 16` 未考虑父容器 `padding: AppSpacing.md`(双侧共32px),分栏模式下溢出
- **修改**: 预览最大宽度改为 `(screenWidth - 32).clamp(200, ∞)`,预留父容器双边距
- **涉及文件**: `lib/features/home/presentation/widgets/quick_card_preview.dart`
#### 5. 灵感页面关联推荐卡片底部溢出 12px
- **Issue**: 关联推荐横向列表容器 `SizedBox(height: 140)` 小于 `FeedItemChip(normal)` 模式实际内容高度
- **修改**: 容器高度从 140 增加到 156
- **涉及文件**: `lib/features/discover/presentation/pages/home/related_recommend_section.dart`
#### 6. RenderFractionalTranslation hitTestChildren 断言错误
- **Issue**: 灵感页面使用 `Transform.translate` 包裹 `CustomScrollView`,下拉刷新时 offset 动态变化触发布局断言 `!debugNeedsLayout`
- **修改**: 用 `Padding(padding: EdgeInsets.only(top: offsetY))` 替代 `Transform.translate(offset: Offset(0, offsetY))`,实现相同视觉效果且不触发断言
- **涉及文件**: `lib/features/discover/presentation/pages/home/inspiration_page.dart`
#### 7. Scrollbar ScrollController 无 ScrollPosition 错误
- **Issue**: 金币记录页 `CupertinoScrollbar` 未指定 controller 参数,默认使用 PrimaryScrollController 导致无 ScrollPosition 可绑定
- **修改**: 新增 `_scrollController` 并同时传给 `CupertinoScrollbar(controller:)``CustomScrollView(controller:)`
- **涉及文件**: `lib/features/user_center/presentation/coin_log_page.dart`
***
## [v6.107.0] - 2026-06-22
### 🏗️ 重构(应用根组件深度职责分离)
#### 1. 快捷操作处理器提取
- **Issue**: 搜索快捷方式逻辑(`_handleSearchShortcut`)和路由导航仍内联在根组件
- **修改**:
- 提取 `QuickActionsHandler`:封装快捷方式回调逻辑(搜索快捷方式 + 路由导航),处理白屏修复逻辑
- 根组件仅调用 `_quickActionsHandler.initialize()`
- **涉及文件**: 新增 `lib/app/services/quick_actions_handler.dart`,修改 `lib/app/app.dart`
#### 2. 小组件导航服务提取
- **Issue**: `_handlePendingWidgetNavigation` 仍留在根组件
- **修改**:
- 提取 `WidgetNavigationService`:封装小组件点击后的待处理导航逻辑
- 生命周期恢复时调用 `_widgetNavigationService.handlePendingNavigation()`
- **涉及文件**: 新增 `lib/app/services/widget_navigation_service.dart`,修改 `lib/app/app.dart`
#### 3. 应用锁生命周期服务提取
- **Issue**: `didChangeAppLifecycleState` 中的应用锁暂停/恢复逻辑仍内联
- **修改**:
- 提取 `AppLockLifecycleService`:封装应用锁在前后台切换时的处理逻辑
- 生命周期回调简化为 `_appLockLifecycleService.onAppPaused()`/`onAppResumed()`
- **涉及文件**: 新增 `lib/app/services/app_lock_lifecycle_service.dart`,修改 `lib/app/app.dart`
#### 4. ThemeSettingsState.toThemeData() 方法
- **Issue**: `AppTheme.buildFromSettings` 在 build 方法中被调用两次light+dark参数传递冗长
- **修改**:
-`ThemeSettingsState` 上添加 `toThemeData()` 方法,封装主题构建逻辑
- build 方法中主题构建从 30+ 行参数简化为 3 行方法调用
- 支持 `isDark` 参数覆盖,用于构建 darkTheme
- **涉及文件**: 修改 `lib/features/settings/providers/theme_settings_provider.dart`
***
## [v6.106.0] - 2026-06-22
### 🏗️ 重构(应用根组件职责分离)
#### 1. 根组件职责过重问题
- **Issue**: `XianyanApp` 承担了10+个不同职责(主题同步、动画配置、数据管理、快捷方式、桌面服务等),违反单一职责原则,代码复杂度高、难以维护和测试
- **修改**:
- 提取 `ThemeSyncService`管理主题状态同步到桌面端macOS/Windows包含窗口特效和托盘图标主题同步内置去重机制
- 提取 `AnimationConfigService`:管理 flutter_animate 全局动画配置(时长、曲线),仅在设置变化时更新
- 提取 `DataManagementService`管理原生数据管理通道MethodChannel处理系统存储清理、数据清除、页面导航
- 提取 `DesktopServicesManager`:统一管理桌面端服务初始化和生命周期(托盘、窗口特效、菜单栏)
- 重构 `app.dart`使用4个服务类替代原有内联逻辑代码量从874行降至689行减少约21%
- 提取 `_buildOhosApp`/`_buildStandardApp`/`_buildGlassThemeData`/`_buildOfflineBanner` 方法,提高 build 方法可读性
- **涉及文件**:
- 新增: `lib/app/services/theme_sync_service.dart`
- 新增: `lib/app/services/animation_config_service.dart`
- 新增: `lib/app/services/data_management_service.dart`
- 新增: `lib/app/services/desktop_services_manager.dart`
- 修改: `lib/app/app.dart`
***
## [v6.105.0] - 2026-06-22
### ✨ 增强(情景诗词交互重构 + 数据管理 + 功能补全)
#### 1. 预选词选择器重构
- **Issue**: 展开分组宽度变化造成视觉跳动,横向滚动单手操作不便,无搜索功能
- **修改**:
- 底部选择器改为纵向网格布局:搜索框 + 分组标题 + 标签芯片网格
- 搜索框实时过滤所有标签
- 分组标题仅视觉分隔,不可点击展开(消除跳动)
- 标签芯片直接点击选中/取消,无需展开/收起
- **涉及文件**: `poetry_widgets.dart`PoetryTagSelector
#### 2. 标签组合选择
- **Issue**: 只能选择单个标签
- **修改**:
- 支持同时选择多个标签(如「秋+雨」组合筛选)
- 已选标签显示在搜索框下方,支持点击取消/清除全部
- `PoetryState.selectedTags``String?` 改为 `List<String>`
- `PoetryNotifier` 新增 `clearSelectedTags()`/`removeSelectedTag()` 方法
- **涉及文件**: `poetry_provider.dart`, `poetry_widgets.dart`
#### 3. 诗词卡片长按菜单
- **Issue**: 底部快捷按钮占用空间且不符合 iOS 交互习惯
- **修改**:
- 使用 `CupertinoContextMenu` 包裹诗词卡片,长按弹出收藏/复制/分享/朗读菜单
- 删除底部快捷按钮(`_buildQuickActions`/`_buildQuickButton`
- **涉及文件**: `poetry_page.dart`
#### 4. 手势操作
- **Issue**: 无法删除单条聊天记录或快速收藏
- **修改**:
- 诗词卡片使用 `Dismissible` 组件
- 右滑显示收藏图标(收藏不移除卡片)
- 左滑显示红色删除按钮(删除该条记录)
- `PoetryNotifier` 新增 `removeChatRecord(id)` 方法
- **涉及文件**: `poetry_page.dart`, `poetry_provider.dart`
#### 5. 聊天记录清空按钮
- **Issue**: 无清空聊天记录入口
- **修改**:
- 诗词页面导航栏添加垃圾桶图标按钮
- 设置页面「数据管理」卡片添加清空按钮
- 点击弹出确认对话框,确认后调用 `clearChatRecords()`
- **涉及文件**: `poetry_page.dart`, `poetry_settings_page.dart`
#### 6. 聊天记录上限提示
- **Issue**: 聊天记录上限 200 条但无提示
- **修改**:
-`chatRecords.length > 180` 时,列表顶部显示黄色提示条
- 设置页面「数据管理」卡片显示 N/200 进度指示
- **涉及文件**: `poetry_page.dart`, `poetry_settings_page.dart`
#### 7. 诗词日历视图
- **Issue**: 无历史诗词查看入口
- **修改**:
- 导航栏添加日历图标按钮
- 点击弹出底部弹窗,按日期分组展示历史诗词
- 使用 `poetryState.poetryRecords` 获取所有诗词记录
- **涉及文件**: `poetry_widgets.dart`PoetryCalendarSheet
#### 8. 统一聊天记录系统
- **Issue**: `poetryHistory``chatRecords` 两套独立系统,数据冗余
- **修改**:
- 合并为统一的 `chatRecords`,删除 `poetryHistory` 字段
- `PoetryChatRecord` 直接存储 `JinrishiciPoetry` 对象(替代 `poetryJson` Map
- 缓存 key 升级为 `poetry_cache_v2`
- **涉及文件**: `poetry_provider.dart`
#### 9. 功能补全
- **Issue**: 设置开关存在但 UI 未渲染(标签、译文、城市/天气)
- **修改**:
- 诗词气泡中根据 `showTags` 渲染标签芯片
- 诗词气泡中根据 `showTranslate` 渲染译文内容
- 聊天列表顶部显示城市/天气信息
- **涉及文件**: `poetry_page.dart`
#### 10. 设置页面增强
- **修改**:
- 新增「使用提示」卡片,包含 7 条功能说明
- 新增「数据管理」卡片,显示聊天记录统计和清空按钮
- **涉及文件**: `poetry_settings_page.dart`
#### 11. 文件拆分
- **修改**:
- `poetry_page.dart`586 行)拆分出 `poetry_tags.dart`(标签定义)和 `poetry_widgets.dart`(选择器+日历组件)
- 所有文件均低于 1000 行限制
- **涉及文件**: 新增 `poetry_tags.dart`, `poetry_widgets.dart`
***
## [v6.104.0] - 2026-06-22
### ✨ 增强(情景诗词预选词选择器 + 城市设置 + 聊天记录持久化)
#### 1. 情景诗词输入框改为预选词芯片选择器
- **Issue**: 情景诗词页面原发送框为自由文本输入,无法有效按标签筛选诗词
- **修改**:
- 将底部输入框替换为预选词芯片选择器,只能选择预定义标签
- 7 个标签分组:气象🌤、时辰🕐、季节🌸、节日🎉、地理🏔、花木🌺、山水⛰
- 标签基于 jinrishici API 推荐关联标签体系(气象/时间/日期/地理/混合标签)
- 点击分组展开标签列表,选择标签后触发诗词刷新
- 当前选中标签高亮显示,支持清除
- **涉及文件**: `poetry_page.dart`
#### 2. 预选词选择后按标签刷新诗词
- **Issue**: 选择预选词后需根据标签获取对应诗词
- **修改**:
- `JinrishiciSdkService` 新增 `fetchSentenceByTag()` 方法
- `PoetryService` 新增 `fetchPoetryByTag()` 方法
- `PoetryNotifier` 新增 `loadPoetryByTag()` 方法
- 选择标签后清除旧 Token 重新请求,触发 API 生成新推荐
- 聊天界面显示用户选择的标签和系统返回的诗词
- **涉及文件**: `jinrishici_sdk_service.dart`, `poetry_service.dart`, `poetry_provider.dart`
#### 3. 设置页面城市选择,影响诗词页面显示
- **Issue**: 情景诗词设置页面城市功能为空壳,修改城市后诗词页面无变化
- **修改**:
- `PoetrySettings` 新增 `city` 字段,持久化到 KvStorage
- 设置页面新增「城市设置」分组卡片
- 城市选择弹窗提供 24 个古诗词名城(长安/洛阳/金陵/临安/姑苏/扬州等)
- 选择城市后同步到 `poetryProvider`,诗词页面显示对应城市
- 城市标签同时触发 `loadPoetryByTag()` 获取对应地域诗词
- **涉及文件**: `poetry_settings_page.dart`, `poetry_provider.dart`
#### 4. 聊天记录持久化保存
- **Issue**: 情景诗词页面聊天记录仅保存在内存,退出即丢失
- **修改**:
- `PoetryState` 新增 `chatRecords` 字段
- 新增 `PoetryChatRecord` 模型type/content/time/poetryJson
- 用户发送的标签、系统提示、返回的诗词全部持久化到缓存
- 最多保留 200 条记录,超出自动清理旧记录
- 下次打开软件可看到历史聊天记录,最新消息在最下面(类似微信/QQ
- `PoetryNotifier` 新增 `addChatRecord()``clearChatRecords()` 方法
- **涉及文件**: `poetry_provider.dart`, `poetry_page.dart`
***
## [v6.103.0] - 2026-06-22
### ✨ 增强(快速卡片多语言全量补全 + 液态玻璃预设视觉实现 + 样式区翻译接入)
#### 1. 12 种语言 quickCard 翻译补全
- **Issue**: 12 种语言zh_tw/ja/ko/fr/de/es/it/pt/ru/ar/hi/bn的 quickCard 字段为英文占位,非中英用户看到英文
- **修复**
- 12 个语言文件全部翻译为各自语言,覆盖 100+ 翻译键
- zh_tw 使用台湾繁体习惯(儲存/相簿/範本/重設/套用/字級)
- ja 使用日文习惯(保存/共有/キャンセル/リセット/テンプレート)
- ko 使用韩文习惯(저장/공유/취소/초기화/템플릿)
- fr/de/es/it/pt/ru/ar/hi/bn 均使用各自语言习惯
- 品牌名 `✨ Slight editor mini``Xianyan` 保持不变
- 中文字体名(宋体/楷体等)翻译为对应语言的字体描述
- **验证**: `flutter analyze` 14 个语言文件全部通过
#### 2. 液态玻璃预设视觉实现iOS 26 风格)
- **Issue**: `CardPresetStyle.liquidGlass` 预设已存在但无液态玻璃视觉效果,仅显示普通渐变
- **修复**
- `QuickCardPreview` 新增 `_buildCardContent()` 方法,当 `presetStyle == liquidGlass` 且平台支持时,使用 `AdaptiveLiquidGlassLayer` 包裹卡片内容
- `LiquidGlassSettings` 参数blur=1.2 / refractiveIndex=1.45 / chromaticAberration=0.6 / lightIntensity=1.0 / ambientStrength=0.5
- 使用 `LiquidRoundedSuperellipse(borderRadius: 12)` 与卡片圆角统一
- 通过 `PlatformCapabilities.supports(CapabilityKey.liquidGlass)` 检测平台能力,不支持时降级为普通渐变
- `applyPreset(liquidGlass)` 补充 `gradientColors` 默认值和 `gradientBegin/End` 方向
- **效果**: 选择液态玻璃预设后,卡片预览区呈现 iOS 26 液态玻璃折射效果
#### 3. 样式调整区全量翻译接入
- **Issue**: `quick_card_style_sections.dart` 中 31 处硬编码中文(栏样式/信息/字体/色深/字号/大小/功能开关/朗读 等)
- **修复**
- `QuickCardStyleSection` / `QuickCardToggleSection` / `QuickCardPresetSection` 新增 `TQuickCard t` 参数
- `_BarStyleRow` / `_BottomInfoRow` / `_FontRow` / `_ColorDepthRow` / `_FontSizeRow` / `_CardSizeRow` / `_TtsToggleItem` 全部接收 `t` 参数
- `_FontRow` 分离 `_fontKeys`(不可翻译的标识符)和 `_fontLabels`(翻译后的显示标签)
- `PresetCard` 新增 `t` 参数,`_label` 使用翻译键
- `quick_card_layouts.dart` 两处调用点传入 `t` 参数
- **文件**
- lib/l10n/languages/zh_tw.dart翻译补全
- lib/l10n/languages/ja.dart翻译补全
- lib/l10n/languages/ko.dart翻译补全
- lib/l10n/languages/fr.dart翻译补全
- lib/l10n/languages/de.dart翻译补全
- lib/l10n/languages/es.dart翻译补全
- lib/l10n/languages/it.dart翻译补全
- lib/l10n/languages/pt.dart翻译补全
- lib/l10n/languages/ru.dart翻译补全
- lib/l10n/languages/ar.dart翻译补全
- lib/l10n/languages/hi.dart翻译补全
- lib/l10n/languages/bn.dart翻译补全
- lib/features/home/presentation/widgets/quick_card_preview.dart液态玻璃效果
- lib/features/home/presentation/widgets/quick_card_style_sections.dart翻译接入
- lib/features/home/presentation/widgets/quick_card_widgets.dartPresetCard 翻译)
- lib/features/home/presentation/widgets/quick_card_state_logic.dartliquidGlass 预设补全)
- lib/features/home/presentation/widgets/quick_card_layouts.dartt 参数传递)
## [v6.102.0] - 2026-06-22
### ✨ 增强(快速卡片创作 Sheet 拆分 + 多语言全量接入 + A/B 对比模式 UI 补全)
#### 1. 文件拆分quick_card_sheet.dart 1345行 → 5 个文件均 < 1000 行)
- **Issue**: `quick_card_sheet.dart` 单文件 1345 行,违反项目"文件不超过 1000 行"规则
- **修复**
- `quick_card_sheet.dart`921 行)— 主入口,保留状态字段、回调、构建方法
- `quick_card_layouts.dart`705 行)— `QuickCardStackedLayout` + `QuickCardSplitLayout` 两种布局
- `quick_card_bars.dart`349 行)— `QuickCardNavBar` + `QuickCardActionBar` + `QuickCardSplitTopBar`
- `quick_card_state_logic.dart`194 行)— 纯逻辑:`stateToJson`/`stateFromJson`/`applyPreset`/`applyAutoPalette`/`resetState`/`resetHomeStyle`
- `quick_card_dialogs.dart`362 行)— 文字编辑对话框 + 更多操作 Sheet + 结果提示
- **验证**: `flutter analyze` 9 个文件全部通过No issues found!
#### 2. 多语言全量接入TQuickCard 翻译类型)
- **Issue**: Sheet 内所有用户可见文案为硬编码中文,不支持多语言切换
- **修复**
- 新增 `lib/l10n/types/t_quick_card.dart`525 行)— 定义 100+ 翻译键
- `T` 根类新增 `quickCard` 字段,集成到 `T.fromMap`/`toMap`
- `zh_cn.dart` / `en.dart` 新增 `quickCard: TQuickCard(...)` 完整翻译
- 主 Sheet 新增 `_t` getter`TQuickCard get _t => ref.read(translationsProvider).quickCard;`
- 18 处硬编码中文文案全部迁移至翻译键(保存失败/已保存到相册/已应用到主页/已复制/已粘贴/剪贴板为空/已清空/已重置/模板保存/模板加载/自动配色/A-B 进入/A-B 恢复/A-B 应用新样式 等)
- 布局组件 `QuickCardStackedLayout` / `QuickCardSplitLayout` / `QuickCardNavBar` / `QuickCardActionBar` / `QuickCardSplitTopBar` 全部接收 `TQuickCard t` 参数
- `QuickCardTextEditorDialog.show()` / `showQuickCardMoreSheet()` / `showQuickCardResult()` 全部接收 `TQuickCard t` 参数
- **动态主题**: 通过 `AppTheme.ext(context)` 获取主题扩展,所有颜色/圆角/阴影均来自主题系统
- **动态样式**: 通过 `ref.watch(translationsProvider)` 实现运行时切换语言无需重启
#### 3. A/B 对比模式 UI 补全(空壳功能完善)
- **Issue**: A/B 对比模式已保存快照,但缺少切换 A/B 视图的 UI 入口
- **修复**
- 预览区新增长按手势 `_toggleAbView()`,切换显示 A 原样式 / B 新样式
- 预览右上角显示当前视图角标A 原样式 / B 新样式),带动画切换
- `_LayoutCallbacks` 新增 `onToggleAbView` 回调
- 布局组件接收 `isAbMode` / `abShowOriginal` / `abSnapshotState` / `abSnapshotHomeStyle` 参数
- **文件**
- lib/features/home/presentation/widgets/quick_card_sheet.dart重写
- lib/features/home/presentation/widgets/quick_card_layouts.dart新建
- lib/features/home/presentation/widgets/quick_card_bars.dart新建
- lib/features/home/presentation/widgets/quick_card_state_logic.dart新建
- lib/features/home/presentation/widgets/quick_card_dialogs.dart修改
- lib/l10n/types/t_quick_card.dart新建
- lib/l10n/types/t_root.dart修改
- lib/l10n/languages/zh_cn.dart修改
- lib/l10n/languages/en.dart修改
## [v6.101.2] - 2026-06-22
### 🐛 修复(托盘导航进入错误 Tab 栈)
#### 0. 托盘菜单点击跳转使用错误 context 导致页面进入错误 Tab 栈
- **Issue**: 托盘 pop 菜单点击跳转时,`DesktopTrayController._navigateTo` 使用 `_ref.context` 调用 `context.appPush(route)`。但 `_ref.context` 可能不属于当前活动 Tab例如窗口失焦期间 Tab 已切换,但 controller 持有的 context 仍是旧 Tab 的),导致非工作台模式下 `GoRouter.push` 把页面压入错误 Tab 的 Navigator。
- **修复**
- `app_router.dart` 新增公开函数 `tabNavigatorKeyFor(int tabIndex)`,按 Tab 索引0=首页/1=发现/2=我的)返回对应的 `GlobalKey<NavigatorState>`,原先 `_homeNavigatorKey`/`_discoverNavigatorKey`/`_profileNavigatorKey` 仍为私有。
- `desktop_tray_controller.dart``_navigateTo` 方法改为:
1. 显式读取 `splitViewProvider.currentTab` 获取当前活动 Tab
2. 通过 `tabNavigatorKeyFor(currentTab)` 拿到当前活动 Tab 的 `navigatorKey.currentContext`
3. 优先使用该 context 进行 `appPush`,确保非工作台模式下 GoRouter.push 进入正确的 Tab 栈
4. 若 tabNavigatorKey 的 context 不可用或未 mounted回退到 `_ref.context`(原逻辑),并打印警告日志
5. 新增 `Log.i` 记录导航目标和当前 Tab便于追踪
- 工作台模式下 `appPush` 内部已通过 `splitViewProvider.currentTab` 决定右栏栈归属,本次修复主要覆盖非工作台模式 / 全屏路由场景
- **文件**
- lib/core/router/app_router.dart新增 `tabNavigatorKeyFor` 公开函数)
- lib/features/desktop/desktop_tray_controller.dart_navigateTo 重构 + 文件头注释更新 + 新增 flutter/widgets.dart 导入)
## [v6.101.1] - 2026-06-22
### 🐛 修复(纯黑模式下 Mac 端托盘图标不可见)
#### 0. 纯黑模式(amoled)下 Mac 端托盘图标手动切换为白色 PNG
- **Issue**: Mac 端使用 `isTemplate: true` 让系统自动反色,但纯黑模式下系统可能将黑色图标保持黑色(因为背景也是黑色),导致托盘图标不可见
- **修复**
- `DesktopTrayService.setIcon` 接口新增 `isAmoled` 参数(默认 false向后兼容
- `TrayManagerTrayService.setIcon` Mac 端分支逻辑更新:
- light 模式:`tray_icon_light.png`(黑色图标)+ `isTemplate: true`
- dark 模式:`tray_icon_light.png`(黑色图标)+ `isTemplate: true`(系统自动反色为白色)
- amoled 模式:`tray_icon_dark.png`(白色图标)+ `isTemplate: false`(手动指定白色,不依赖系统反色)
- `DesktopTrayController.onThemeChanged` 新增 `isAmoled` 参数透传
- `app.dart` 新增 `_lastDesktopAmoledState` 字段,单独跟踪 amoled 状态
dark 和 amoled 的 `effectiveIsDark` 均为 true需单独检测 dark↔amoled 切换)
- Windows/Linux 端逻辑保持不变
- **文件**
- lib/core/services/desktop/desktop_tray_service.dart接口签名 + Stub 实现)
- lib/core/services/desktop/implementations/tray_manager_tray_service.dartMac 端逻辑)
- lib/features/desktop/desktop_tray_controller.dartonThemeChanged 透传 isAmoled
- lib/app/app.dart跟踪 amoled 状态并传入 onThemeChanged
## [v6.101.0] - 2026-06-22
### 🐛 修复(鸿蒙端"编辑此句"按钮解除限制)
#### 0. 鸿蒙端"编辑此句"按钮解除限制
- **Issue**: 创作卡片页面的"编辑此句"按钮,鸿蒙端点击会显示"敬请期待",无法进入编辑器
- **修复**
- 移除 `sentence_detail_actions.dart``if (pu.isOhos) { AppToast.showInfo('敬请期待'); return; }` 限制
- 移除 `sentence_detail_sheet.dart` 中相同的限制逻辑
- 清理未使用的 `platform_utils` 导入
- 鸿蒙端现在可以直接跳转到 `/editor?text=...` 进入编辑器
- **依据**: `/editor` 路由在鸿蒙端正常注册(`route_registry.dart:1130-1138``EditorPage` 无平台限制
- **文件**
- lib/features/home/presentation/panels/sentence_detail_actions.dart修改
- lib/features/home/presentation/providers/sentence_detail_sheet.dart修改
### ✨ 增强(快速卡片创作 Sheet 功能升级 — 模板/壁纸/取色/A-B 对比/动效)
#### 1. 模板管理 UI 完善
- **Issue**: `_saveAsTemplate` 已实现保存,但"加载模板"在更多操作菜单中只是占位,未实现模板列表选择对话框
- **修复**
- 新增 `quick_card_template_sheet.dart`~400 行)— 模板管理底部面板
- 数据模型 `QuickCardTemplate`key/stateJson/homeStyleJson/savedAt/isFavorite
- 列表排序:收藏优先 + 时间倒序
- 使用 `AppSlidable` 实现左滑收藏/取消收藏 + 右滑删除
- 模板项含预览缩略图(背景色/渐变 + 文字摘要)
- 点击模板项返回并还原 QuickCardState + DailyCardStyle
- 通过 `Hive.box<dynamic>('app').keys` 直接获取所有模板键
- **更多操作菜单新增**`loadTemplate('📂 加载模板')``abCompare('⚖️ A/B 对比')`
#### 2. 颜色选择器升级(最近使用 + 吸管取色)
- **Issue**: 28 色预设 + HSL 滑块交互偏简陋,缺少吸管取色和最近使用记录
- **修复**
- 新增 `quick_card_color_section.dart`~480 行)— 独立颜色选择模块
- 顶部增加最近 6 色横条,持久化到 KvStorage`quick_card_recent_colors` 键)
- 吸管取色:`image_picker` 选图 → `package:image` 解码 → 3x3 网格采样取平均色
- 颜色选择器对话框升级28 色预设 + 最近使用 + HSL 三滑块
- 7 预设色 + 自定义入口 + 吸管取色按钮
- **修复 CupertinoIcons eyedropper 未定义**:改为 `Icons.colorize`Material 图标)
#### 3. 壁纸库接入
- **Issue**: 背景图片选择路径单一,仅支持从相册选择,未支持从项目内置壁纸库选择
- **修复**
- 新增 `quick_card_background_section.dart`~560 行)— 独立背景选择模块
- `_WallpaperLibrarySheet` 底部面板来源切换栏12 源)+ 网格 + 长按预览
- 复用 `features/template``wallpaperProvider` + `WallpaperPreviewSheet`
- 背景选择行新增"从壁纸库选择"入口
- 网络壁纸 URL 通过 `imagePath` 字段存储
#### 4. 文件拆分quick_card_style_sections.dart 917行 → 430行
- **Issue**: `quick_card_style_sections.dart` 文件过大,违反单一职责
- **修复**
- `_BackgroundRow` + `_GradientAngleChip``quick_card_background_section.dart`
- `_ColorRow``quick_card_color_section.dart`
- `QuickCardStyleSection` 新增 `onAutoPalette` 参数
- 移除 `image_picker``logger` 导入(已迁移到子文件)
#### 5. A/B 对比模式
- **Issue**: 调整样式时无法对比"原样式"与"新样式"
- **修复**
- 新增 `_abSnapshotState``_abSnapshotHomeStyle``_isAbMode` 字段
- `_enterAbMode()`:保存当前样式快照
- `_exitAbMode({bool restore})`:恢复原样式或保留新样式
- 更多操作菜单新增 `⚖️ A/B 对比` 切换项
#### 6. adaptive_palette 自动配色
- **Issue**: 用户配色困难,需要手动调整
- **修复**
- 背景选择行新增"自动配色"入口
- `_extractAutoPalette` 调用 `AdaptiveThemeService.extractFromProvider(provider)`
- 提取主色/辅助色/表面色应用到背景渐变 + 文字颜色
- `BackgroundLayerPipe` 扩展支持链式调用
#### 7. 交错入场动画flutter_staggered_animations
- 样式调整区各项使用 `AnimationLimiter` + `AnimationConfiguration.staggeredList`
- `SlideAnimation` + `FadeInAnimation` 实现交错入场
#### 8. Hero 过渡动画
- `SafePreview` 外包裹 `Hero(tag: 'quick_card_preview', flightShuttleBuilder: ...)`
- 从首页点击创建到 Sheet 弹出使用 Hero 过渡
#### 9. 触觉反馈增强
- 新增差异化触觉方法:
- `_fireLightHaptic()` — 滑块/微调HapticService.light
- `_fireMediumHaptic()` — 选择/确认HapticService.medium
- `_fireSuccessHaptic()` — 保存/完成HapticService.success
- 滑块类回调(字号/色深)调用 `_fireLightHaptic()`
- 分享调用 `_fireMediumHaptic()`,保存/应用调用 `_fireSuccessHaptic()`
#### 10. 网络图片背景支持
- **Issue**: `quick_card_preview.dart` 使用 `Image.file` 渲染背景,壁纸库返回的 URL 无法加载
- **修复**
- 新增 `_buildImage(path, fallback)` 辅助方法
- 自动识别 `http://` / `https://` 前缀,分别使用 `Image.network` / `Image.file`
- 错误回退到纯色背景
- **文件**
- lib/features/home/presentation/widgets/quick_card_sheet.dart修改
- lib/features/home/presentation/widgets/quick_card_style_sections.dart修改
- lib/features/home/presentation/widgets/quick_card_background_section.dart新建
- lib/features/home/presentation/widgets/quick_card_color_section.dart新建
- lib/features/home/presentation/widgets/quick_card_template_sheet.dart新建
- lib/features/home/presentation/widgets/quick_card_dialogs.dart修改
- lib/features/home/presentation/widgets/quick_card_preview.dart修改
***
## [v6.100.0] - 2026-06-22
### 🐛 修复API 拦截器 401 错误处理优化)
#### 1. Token 静默刷新(提前 5 分钟)
- **Issue**: 之前移除了 token 自动刷新逻辑,用户长时间使用后 token 过期需手动重新登录,体验不好
- **修复**
- `TokenService` 新增 `_cachedExpiresAt` 缓存字段,由 `checkToken`/`refreshToken` 在获取 `expires_in` 后自动更新
- `TokenService` 新增 `silentRefreshIfExpiringSoon()` 方法:基于缓存的过期时间判断是否即将过期(提前 5 分钟 = 300 秒),若即将过期则调用 `refreshToken` 静默刷新
- `ApiInterceptor.onRequest` 在每次请求前 fire-and-forget 调用静默刷新(不阻塞当前请求)
- 跳过 `/api/token/` 开头的请求,避免对 token 管理接口本身触发刷新(防止递归)
- 并发安全:复用 `TokenService._isRefreshing` 锁,多个请求同时触发只刷新一次
- 刷新失败不阻塞:原 Token 继续使用直到 401由 401 处理逻辑引导用户重新登录
- 刷新成功后若响应未包含 `expires_in`设置默认过期时间2 小时)避免重复触发刷新
#### 2. 401 友好提示Toast 替代对话框)
- **Issue**: 401 时无任何提示,用户不知道需要重新登录
- **修复**
- `_handleAuthExpired` 新增 `AppToast.showWarning('登录已过期,请重新登录')` 友好提示
- 使用 Toastbot_toast而非对话框不打断用户当前操作
- 带节流机制3 分钟内不重复提示,避免多个并发请求同时 401 时弹出多次 Toast
- 保留 warning 级别日志(不恢复 error 级别)
- 不重试请求(避免死循环)
- **文件**lib/core/network/api_interceptor.dart、lib/core/services/auth/token_service.dart
***
> v6.99.0 及更早版本v6.87.0 ~ v6.99.0)已归档至软件特性功能文档。
> 主要特性概览:
> - **v6.99.0**: 快速卡片创作 Sheet 拆分1547行→4文件+ 空壳功能补全11项字号滑块/背景图片/渐变方向/自定义颜色器/字体扩展/更多操作菜单/导出格式区分/自动播放循环/TTS朗读指示/模板保存/重置确认)+ 拆分过程修复(触觉音效补回/滑块过度反馈/TTS订阅泄漏/色深滑块宽度)+ 文本编辑对话框升级
> - **v6.98.0**: 10项桌面端问题集中修复窗口关闭对话框/托盘工作台模式/创作卡片侧栏/编辑器按钮/macOS窗口大小/托盘三段式深色/托盘icon/401错误
> - **v6.97.1**: 7项问题修复后的体验优化扩展密码强度检测/稍后读气泡卡片交互/灵感朗读/情景诗词滑动/设置交互/日签换一句/使用报告性能与CSV导出
> - **v6.97.0**: 7项软件问题集中修复密码修改前端/稍后读气泡卡片按钮/灵感朗读/情景诗词滑动空白/情景诗词设置/日签换一句/使用报告数据为空)
> - **v6.96.0**: Windows 桌面端窗口大小预设菜单3×2 网格)+ 托盘菜单窗口大小子菜单 + 工作台模式导航栏位置切换
> - **v6.95.0**: 鸿蒙端专项修复(横屏翻转/复制粘贴/设备信息/键盘可见性/READ_PASTEBOARD 权限/正则崩溃)+ SDK 零修改原则
> - **v6.94.5**: 工作台设置页 Slider 崩溃修复CupertinoSlider 替换)+ 移动端横屏工作台布局空白修复
> - **v6.94.4**: 工作台布局修复(拖拽 clamp 逻辑/双栏注释/pop canPop 检查)
> - **v6.94.3**: 工作台模式白屏修复appPop/appCanPop 工作台感知)+ 闲情逸致页面 ref 卸载报错修复
> - **v6.93.1**: MethodChannel 命名风格统一为 `apps.xy.xianyan/{feature}` 风格
> - **v6.93.0**: 桌面端原生功能扩展第二批剪贴板富文本HTML/侧边栏折叠记忆/分屏记忆/可拖拽导航栏/Windows Mica Alt 特效)
> - **v6.92.0**: macOS 原生功能扩展Touch Bar/NSSharingService 共享面板/NSDockTile 徽章/NSStatusItem 菜单栏金句/CoreSpotlight 索引)
> - **v6.91.2**: 深度链接服务完善xianyan:// scheme 跳转note/sentence/readlater 路由映射)
> - **v6.91.1**: 笔记编辑页桌面端拖拽文件接入(图片 base64/文本追加/文件链接)
> - **v6.91.0**: 桌面端原生增强(系统托盘/macOS 菜单栏/自定义标题栏/Windows 原生能力/窗口特效/动态主题/工作台设置页)
> - **v6.90.1**: 工作台模式多语言支持 + 中栏宽度 KvStorage 持久化
> - **v6.90.0**: PC工作台布局重构微信PC式三栏 WorkbenchLayout + RightPanelStackNotifier + 路由拦截)
> - **v6.89.1**: macOS MissingPluginException 修复 + Expanded 布局错误修复
> - **v6.89.0**: 评分弹窗商店名称多语言 + Beta问卷按钮隐藏跨平台修复
> - **v6.88.0**: 闲情逸致价格档位扩展6档+ 纠错历史本地缓存drift+ 学习计划详情页 + 闲情逸致全模块多语言
> - **v6.87.0**: 多平台应用商店统一服务AppStoreService+ 学习计划重构预告 + 闲情逸致"免费"改"平价" + 纠错页全面多语言