Files
xianyan/CHANGELOG.md
Developer 81ea0f60dc fix: 修复 FactoryReset 误删用户文件并将应用数据迁移至 Application Support
- 修复 macOS/Windows/Linux 非沙盒下 FactoryReset 递归删除 ~/Documents 导致用户项目源代码丢失的严重 bug,改为仅删除已知应用专属文件/子目录并增加路径安全校验

- 数据库文件从 getApplicationDocumentsDirectory() 迁移到 getApplicationSupportDirectory()(应用专属),含自动迁移逻辑

- 启用 macOS Debug 模式沙盒,使开发环境与生产环境路径行为一致

- 统一迁移 13 处应用数据存储位置(Hive、聊天附件、字体、稍后读同步等)到 Application Support,应用启动时执行一次性迁移

- backup_service.dart 备份文件迁移至 Application Support,getBackupList() 兼容扫描新旧两个路径并去重

- clearCache() 同样修复危险递归清空逻辑

详见 CHANGELOG.md v6.136.0 ~ v6.138.0
2026-06-26 08:46:23 +08:00

149 KiB
Raw Blame History

Changelog

所有重要变更均记录于此文件。格式基于 Keep a Changelog

保留最近 14 个版本v6.101.0 ~ v6.120.0。更早版本v6.87.0 ~ v6.100.0)的特性已合并进软件特性功能文档,详见文末归档概览。


[v6.138.0] - 2026-06-26

🔧 全量迁移应用数据至 Application Supportv6.137.0 后续)

背景

v6.137.0 完成了数据库文件和 Debug 沙盒的迁移,但项目中仍有 13 处使用 getApplicationDocumentsDirectory() 存储应用内部数据Hive、聊天文件、字体等。本次统一迁移所有应用内部数据到 getApplicationSupportDirectory(),并修复 clearCache() 中与 FactoryReset 同样的危险清空逻辑。

新增工具函数

lib/core/utils/platform/path_provider_native.dart

  • 新增 getAppDataDirectory():返回 getApplicationSupportDirectory(),推荐用于应用内部数据
  • 新增 migrateAppDataFromDocumentsToSupport():一次性迁移函数
    • 迁移已知应用子目录:image_cachereadlater_syncchat_audiochat_attachmentschat_trashcloud_cachefile_transferfontsbackups
    • 迁移 Hive 文件:*.hive*.lock
    • 使用 copy 而非 rename复制成功后才删除旧文件
    • 若新路径已存在同名文件/目录,跳过(避免覆盖)
    • 进程内缓存迁移状态,避免重复执行

lib/core/utils/platform/platform_utils.dart

  • 新增 safeAppDataPath getter暴露 getAppDataDirectory()
  • 新增 migrateAppData() 函数:暴露迁移逻辑

lib/main.dart

  • KvStorage.init() 之前调用 pu.migrateAppData(),确保存储初始化时使用新路径

替换的使用点13 处)

文件 修改内容
hive_safe_access.dart Hive.init 从 Hive.initFlutter() 改为 Hive.init(applicationSupportPath),降级方案保留 Documents
image_cache_metadata_service.dart 索引重建扫描新路径,兼容旧路径残留
readlater_device_sync_service.dart 同步文件保存到新路径,扫描兼容新旧路径
chat_audio_service.dart 录音文件存储到新路径
chat_file_service.dart 附件存储到新路径,路径解析兼容新旧
cloud_cache_service.dart 云端缓存存储到新路径
cache_manager_service.dart 文件传输缓存存储到新路径
font_download_service.dart 字体文件存储到新路径
font_management_notifier.dart 字体扫描新路径

修复 clearCache() 危险清空逻辑

lib/features/settings/providers/general_settings_provider.dart

clearCache() 方法存在与 FactoryReset 同样的危险逻辑:遍历 getApplicationDocumentsDirectory() 返回目录的所有子项并递归删除。在 macOS/Windows/Linux 非沙盒下会删除用户 ~/Documents 下所有内容。

修复方案:

  1. 临时目录:直接清空内容(应用专属,安全)
  2. Application Support:带路径校验的清空(要求路径包含 apps.xy.xianyanxianyan
  3. Documents:仅清理已知应用子目录(image_cachechat_audiochat_attachments 等 9 个),不删除根内容
  4. 新增 _safeClearDirContents() 辅助方法,支持路径校验

保留的使用点(用户可见文件)

以下使用点保留 getApplicationDocumentsDirectory(),因为存储的是用户可见文件:

  • data_management_export_mixin.dart:数据导出 .xypk 文件(导出后通过 share_plus 分享,路径不重要临时文件)

backup_service.dart 备份迁移(补充)

lib/core/services/data/backup_service.dart

  • backupDirPathsafeAppDirPathDocuments改为 safeAppDataPathApplication Support
  • getBackupList() 兼容新旧两个路径:同时扫描 Application Support 和 Documents合并结果并按文件名去重
  • 新增 _scanBackupDir() 私有方法,提取目录扫描逻辑

lib/core/utils/platform/path_provider_native.dart

  • 修正迁移子目录列表:backupsxianyan_backups(与 backup_service.dart_backupDirName 保持一致)

lib/features/settings/presentation/more_settings_page.dartlib/features/settings/providers/general_settings_provider.dart

  • Documents 目录清理列表新增 xianyan_backups 子目录
  • FactoryReset 的 _safeClearAppFilesystemData() 新增步骤 6.5:清理 Documents 下已知应用子目录

验证

  • flutter analyze 所有修改文件 → No issues found
  • 迁移逻辑在应用启动时自动执行,用户无感知
  • 兼容旧路径残留文件,迁移失败不影响使用

[v6.137.0] - 2026-06-26

🔧 数据库路径迁移 + Debug 沙盒启用v6.136.0 后续优化)

背景

v6.136.0 修复了 FactoryReset 误删项目源代码的严重 bug但暴露出两个深层问题

  1. 数据库文件位置(getApplicationDocumentsDirectory())在桌面非沙盒下不理想
  2. Debug 模式未启用沙盒,导致开发环境与生产环境路径行为不一致(这是 bug 复现的根源)

本版本实施两个优化建议,从根因层面避免类似问题再次发生。


建议 1数据库文件迁移至应用专属目录

修改文件

lib/core/storage/database/database_connection/native.dart

路径变更

平台 旧路径 新路径
macOS 非沙盒 ~/Documents/xianyan.db ~/Library/Application Support/apps.xy.xianyan/xianyan.db
macOS 沙盒 ~/Library/Containers/.../Data/Documents/xianyan.db ~/Library/Containers/.../Data/Library/Application Support/xianyan.db
iOS <app>/Documents/xianyan.db <app>/Library/Application Support/xianyan.db
Windows ~/Documents/xianyan.db %APPDATA%/<vendor>/<app>/xianyan.db
Linux ~/Documents/xianyan.db ~/.local/share/<app>/xianyan.db
Android /data/data/<pkg>/files/xianyan.db /data/data/<pkg>/files/xianyan.db(路径相同,无影响)

自动迁移逻辑

新增 _resolveDatabaseFile() 方法,在 LazyDatabase 初始化阶段执行:

  1. 新路径已存在 → 直接使用(迁移已完成或全新安装)
  2. 旧路径存在数据库文件 → 复制到新路径(含 -wal/-shm/-journal 辅助文件),删除旧文件
  3. 都不存在 → 使用新路径(首次安装)
  4. 迁移失败 → 回退到旧路径,保证数据可访问

安全性保障

  • 使用 copy 而非 rename,复制成功后才删除旧文件,避免迁移中断导致数据丢失
  • 迁移在 LazyDatabase 初始化阶段执行,此时数据库未打开,无并发风险
  • 详细的日志记录迁移过程,便于排查问题

联动修改

lib/features/settings/presentation/more_settings_page.dart

  • _safeClearAppFilesystemData() 方法第 6.1 步扩展:同时清理新旧两个路径下的数据库文件
    • 新路径:getApplicationSupportDirectory()/xianyan.db
    • 旧路径:getApplicationDocumentsDirectory()/xianyan.db(兼容历史版本残留)

建议 2启用 Debug 沙盒

修改文件

macos/Runner/DebugProfile.entitlements

  • com.apple.security.app-sandboxfalsetrue

决策过程

启用 Debug 沙盒与建议 1 存在冲突:

  • 沙盒内应用无法访问沙盒外路径
  • 若先迁移数据库到沙盒外的 ~/Library/Application Support/apps.xy.xianyan/,再启用沙盒,迁移逻辑会尝试从沙盒外旧路径复制,但沙盒内应用无权访问 → 迁移失败

经用户确认,选择"启用 Debug 沙盒 + 接受数据丢失"方案:

  • 项目源代码不会丢失IDE 进程不受沙盒影响)
  • ⚠️ Debug 模式下应用内数据(数据库、收藏、历史等)会丢失,开发者需重新登录/创建
  • 长期收益:开发环境与生产环境路径行为一致,避免类似 bug 复现

沙盒启用后路径变化Debug 模式)

API 启用前(非沙盒) 启用后(沙盒)
getApplicationDocumentsDirectory() ~/Documents ~/Library/Containers/apps.xy.xianyan/Data/Documents
getApplicationSupportDirectory() ~/Library/Application Support/apps.xy.xianyan ~/Library/Containers/apps.xy.xianyan/Data/Library/Application Support
getTemporaryDirectory() ~/Library/Caches/apps.xy.xianyan ~/Library/Containers/apps.xy.xianyan/Data/Library/Caches

影响范围评估

  • Hive 存储:迁移到沙盒内 Documents安全
  • 图片缓存元数据:迁移到沙盒内 Documents安全
  • 聊天音频/文件:迁移到沙盒内 Documents安全
  • 字体下载服务:迁移到沙盒内 Documents安全
  • LocalSend 文件接收:存储在应用专属目录,不依赖 ~/Downloads,安全
  • 稍后读同步:迁移到沙盒内 Documents安全
  • Flutter 调试Dart VM Service 通过 localhost 通信,沙盒允许 localhost 网络访问

用户须知

  • Debug 模式下首次启动会显示空数据库,需重新登录账户
  • 旧 Debug 数据库文件残留在沙盒外路径,可手动清理:
    • ~/Documents/xianyan.db
    • ~/Library/Application Support/apps.xy.xianyan/xianyan.db

举一反三

  1. 其他使用 getApplicationDocumentsDirectory() 的位置:项目中仍有 13 处使用此 API 存储应用数据Hive、图片缓存、聊天文件、字体、稍后读等。本次未一并迁移因为

    • 启用沙盒后,这些路径自动变为应用专属(沙盒内 Documents不再有污染问题
    • 桌面非沙盒场景下仍有潜在风险,但优先级低于数据库
    • 后续可考虑统一迁移到 getApplicationSupportDirectory()
  2. 数据库迁移日志监控:建议在 Release 模式下监控 Database migration: 日志,了解用户迁移情况,及时发现问题

  3. 沙盒启用后的回归测试:建议在 Debug 模式下测试以下功能:

    • 数据库创建/读写
    • 文件下载(字体、图片)
    • LocalSend 文件接收
    • 相机/麦克风权限
    • 定位功能

[v6.136.0] - 2026-06-26

🚨 严重 Bug 修复(数据丢失 - macOS/Windows/Linux 非沙盒模式)

背景

用户反馈macOS Debug 模式下,进入「更多设置 → 重置与清理 → 清空软件所有数据」输入"重置"确认后,整个项目源代码文件全部丢失

根因

lib/features/settings/presentation/more_settings_page.dart_executeFactoryReset 方法第 6 步缓存清理逻辑存在严重缺陷:

// ❌ 原 dangerous 代码
final dirs = <Directory>[];
dirs.add(await getTemporaryDirectory());
dirs.add(await getApplicationDocumentsDirectory());  // macOS 非沙盒 → ~/Documents
dirs.add(await getApplicationSupportDirectory());

for (final dir in dirs) {
  await for (final entity in dir.list()) {
    if (entity is Directory) {
      await entity.delete(recursive: true);  // 递归删除子目录!
    }
  }
}
  • macOS Debug 模式下 DebugProfile.entitlementscom.apple.security.app-sandbox = false(未启用沙盒)
  • 非沙盒模式下 getApplicationDocumentsDirectory() 返回用户级 ~/Documents(不是应用容器目录)
  • 数据库连接 native.dart#L27-L28xianyan.db 放在 ~/Documents/xianyan.db
  • 代码遍历 ~/Documents 下所有子项并递归删除 → ~/Documents/trae_projects 被递归删除 → 整个项目源代码丢失
  • 同样的危险在 Windows/Linux 非沙盒下都存在

修复方案

lib/features/settings/presentation/more_settings_page.dart

  1. 新增 _safeClearAppFilesystemData() 方法,遵循三大安全原则:

    • 永不递归删除 getApplicationDocumentsDirectory() 等返回目录的根内容
    • 仅删除已知应用专属路径(数据库文件、应用标识子目录)
    • 路径校验:清理子目录前验证路径包含 apps.xy.xianyanxianyan,否则跳过
  2. 精确删除数据库文件:仅删除 xianyan.dbxianyan.db-walxianyan.db-shmxianyan.db-journal,不遍历父目录

  3. _safeClearDirectoryContents() 通用方法

    • requireAppIdentifier 参数:要求路径包含应用标识才清理
    • 仅清空目录的直接子项,不删除目录本身
    • 单个文件删除失败不影响整体清理
    • 详细的日志记录
  4. 分层清理策略

    • 数据库文件:精确文件删除(无条件)
    • 临时目录:直接清空(应用专属,安全)
    • 应用支持目录:带路径校验的清空
    • 应用缓存目录:直接清空(应用专属,安全)
    • Flutter ImageCache内存缓存清理

影响范围

  • macOS 非沙盒Debug 模式):修复项目源代码丢失问题
  • Windows 非沙盒:修复 Documents 目录被清空问题
  • Linux 非沙盒:修复用户主目录被清空问题
  • iOS/Android 沙盒:原行为正常,现增加路径校验作为防御
  • macOS Release 沙盒模式:原行为正常,现增加路径校验作为防御

举一反三

  • 数据库连接文件位置(native.dart)使用 getApplicationDocumentsDirectory() 在桌面非沙盒下不理想,建议未来迁移至 getApplicationSupportDirectory()(应用专属,更安全)
  • 「数据管理页面」的 _clearAllData 方法仅清理数据库表,不涉及文件系统删除,安全
  • 「缓存管理页面」的清理操作通过 CacheService 调用,使用应用专属路径,安全

[v6.135.0] - 2026-06-26

🧹 仓库瘦身(历史大文件清理)

背景

远程仓库体积膨胀至 598 MBGitea 服务端统计),本地 .git 277 MB。历史中累积了大量第三方二进制、服务端运行产物与调试截图导致单次 git push 触发 Nginx HTTP 413请求体过大

操作(git-filter-repo 改写全部历史)

从所有历史提交中移除以下路径:

路径 类型 说明
windows/local_packages/sqlite3/nuget_test/ 第三方二进制 NuGet 测试包(多平台 .so/.dll/.dylibFlutter 项目不该提交
docs/toolsapi/public/compress/ 服务端产物 图片压缩缓存
docs/toolsapi/public/uploads/ 用户上传 服务端运行时数据,绝对不该入库
docs/toolsapi/public/base64/ 服务端产物 base64 编码图片
packages/liquid_glass_easy/showcases/ 展示资源 gif 演示文件
debug_*.png(根目录 6 个) 调试截图 误提交的调试截图

保留(构建/运行依赖)

  • windows/local_packages/sqlite3/prebuilt/sqlite3.dll3.1 MBwindows/CMakeLists.txt:116 引用Drift 数据库 Windows 端依赖,已从备份恢复
  • docs/toolsapi/public/qqwry.dat / file.json:服务端运行依赖,本次保留待评估
  • assets/images/empty/rz.png / iOS AppIcon建议后续压缩替换不从历史删除

.gitignore 新增

  • /docs/toolsapi/public/{compress,uploads,base64}/
  • /debug_*.png/ohos_run_log.txt/build_log.txt

效果

  • 本地 .git277 MB → 60 MB降 78%
  • 改写 113 个提交HEAD 由 6c8c2e24d01863d0
  • 备份:/tmp/xianyan-backup-20260626-074855.bundle164 MB
  • ⚠️ 协作者需重新 clone历史已改写force push 覆盖远程)

[v6.134.0] - 2026-06-26

🛠 修复App Store 审核合规 - Guideline 2.4.5(i) / 2.1(a)

背景

App Store 审核驳回 v6.6.25 (2606260),提出 3 项问题:

  1. 2.4.5(i) 三个 entitlement 缺少匹配功能:files.downloads.read-write / files.downloads.read-only / network.server
  2. 2.4.5(i) 沙盒缺少必需 entitlementdevice.camera(相机功能)/ personal-information.location(定位功能)
  3. 2.1(a) 权限管理页点击「相册/存储/麦克风请求」时显示错误(MissingPluginException

1. Entitlements 文件修订macOS 沙盒合规)

macos/Runner/Release.entitlements + DebugProfile.entitlements

操作 Entitlement 说明
新增 com.apple.security.device.camera 相机:扫码/拍照生成卡片/OCRAVCaptureDevice via PermissionManager.swift
新增 com.apple.security.device.microphone 麦克风:语音录制/转文字AVCaptureDevice via PermissionManager.swift
新增 com.apple.security.personal-information.location 定位permission_handler 依赖链引用 CoreLocation 符号,沙盒需此 entitlement
删除 com.apple.security.files.downloads.read-only 代码无 getDownloadsDirectory 调用,确属冗余
删除 com.apple.security.files.downloads.read-write 同上
保留 com.apple.security.network.server LocalSend 局域网文件传输实际使用:HttpServer.bindSecure / ServerSocket.bind

2. Info.plist 补全 Usage Description

  • 新增 NSLocationUsageDescription声明定位用途IP 大致区域,不获取精确 GPS
  • 已存在:NSCameraUsageDescription / NSMicrophoneUsageDescription / NSPhotoLibraryUsageDescription

3. 权限管理 Bug 修复(替代 permission_handler_apple 的 macOS 空实现)

根因permission_handler_apple 9.4.9 仅支持 iOS无 macOS 实现,调用 Permission.camera.status 等方法时抛出 MissingPluginExceptionUI 显示错误提示。

修复方案:新增原生权限管理器,通过 MethodChannel 暴露给 Dart 端。

  • macos/Runner/PermissionManager.swift(新文件)

    • 支持 4 类权限:camera / microphone / photos / notification
    • 基于 AVFoundation / Photos / UserNotifications framework
    • 状态字符串与 Dart 侧 AppPermissionStatus 枚举对齐:notDetermined / granted / permanentlyDenied / restricted
    • openSystemSettings 跳转「隐私与安全性」面板macOS 无法深链到子页面)
  • macos/Runner/AppDelegate.swift

    • 注册 MethodChannel apps.xy.xianyan/macos.app 三个方法:
      • checkPermissionPermissionManager.checkStatus
      • requestPermissionPermissionManager.requestPermission
      • openPermissionSettingsPermissionManager.openSystemSettings
  • macos/Runner.xcodeproj/project.pbxproj

    • 注册 PermissionManager.swift 到 Runner targetPBXBuildFile + PBXFileReference + Sources
  • lib/core/services/auth/permission_service.dart

    • AppPermission.macosPermissionName 新增属性:返回原生权限名称字符串
    • AppPermission.localServer 新增虚拟权限:用于 UI 解释 network.server entitlement 对应的 LocalSend 功能
    • AppPermission.isPlatformRelevant 全平台适配macOS/Windows/Linux/Web 各自过滤
    • PermissionService.checkStatus macOS 分支:调用 MacosPlatformService.checkPermission
    • PermissionService.requestPermission macOS 分支:调用 MacosPlatformService.requestPermission
  • macos/Runner/MainFlutterWindow.swift

    • Impeller 开关修复setenv 方式已废弃,改为 FlutterDartProject.commandLineArguments 传递 --enable-impeller/--no-enable-impeller

4. App Store Connect 回复要点

  • network.serverLocalSend 局域网文件传输HttpServer.bindSecure / ServerSocket.bind
    • 用户入口路径:① "我的" → "我的设备" → "文件传输助手"卡片 ② "发现" tab → "文件传输助手"会话(📁 emoji ③ Spotlight 搜索 "文件传输" → 跳转 ④ 二维码扫描 xianyan://transfer scheme
  • downloads.read-*:已删除(无匹配功能)
  • device.camera / personal-information.location:已添加
  • device.microphone补加PermissionManager.swift 用到 AVCaptureDevice audio
  • Bug 修复:permission_handler_apple 无 macOS 实现,已替换为原生 PermissionManager

5. 防御性决策记录

  • 麦克风 entitlement补加Apple 仅点名 cameraPermissionManager.swift 同时调用 AVCaptureDevice.requestAccess(for: .audio),没麦克风 entitlement 同样会被 TCC 拒绝。一并加上避免下次因麦克风被拒再次返工。
  • 定位 entitlement防御性添加:闲言 APP 实际不用 GPS仅因 permission_handler 二进制含 CoreLocation 符号被 Apple 静态扫描到。更彻底的做法是 fork 该插件移除 location 部分,但成本高,添加 entitlement 是性价比最高的方案。
  • LocalSend 入口路径:用户可通过 4 个入口触发文件传输功能(详见上方"用户入口路径"),向 Apple 解释 network.server 的实际使用场景。

影响范围

  • macOS 端权限管理页面可正常请求相机/麦克风/相册/通知权限
  • 沙盒合规,所有 entitlement 都有匹配功能或代码引用
  • 不影响 iOS / Android / 鸿蒙 / Windows / Linux 端
  • ⚠️ 注意:删除 downloads entitlement 后,若未来需要"保存到下载目录"功能需重新添加

[v6.133.0] - 2026-06-26

新增(隐私政策多端对齐 + 关于页 DUNS 入口 + GDPR 欧盟代表澄清)

背景

v6.132.0 在隐私政策中新增了「主体信息」章节披露 D-U-N-S 编号,但遗留 4 个待办:① 关于页未同步展示 DUNS,多端不一致;② 「十二、国际数据保护」声明已指定欧盟代表但未披露具体身份,违反 GDPR Art.27;③ 网页英文区比中文区少 8 个章节(历史遗留不对齐);④ App 内隐私政策简版(9 章)与网页详版(16+ 章)内容详细程度不一致。本次一次性解决全部 4 项。

1. 任务A:关于页同步展示 D-U-N-S

新增 2 个翻译字段到 t_about.dart:

  • entityInfoMenu / entityInfoMenuDesc — 用于关于页「法律信息」区块的新菜单项
  • 14 个语言文件全部补全(zh_CN/zh_TW/ja/ko/de/it/es/fr/pt/ru/ar/bn/hi/en)
  • 法语/意大利语译文含撇号,使用双引号包裹

about_page.dart _LegalSection 新增菜单项:

  • 图标 CupertinoIcons.building_2_fill — 主体信息入口
  • 点击触发 _showEntityInfoDialog 弹窗
  • 弹窗用 CupertinoAlertDialog + SingleChildScrollView + Column,展示 7 个字段(主体名称/DBA/DUNS/统一社会信用代码/注册地址/行业/邮箱),中英对照,底部说明 Dun & Bradstreet 认证
  • 所有标签使用 AppTypography.caption2,标签 w600 加粗,值正常字重,符合 iOS HIG

2. 任务B:GDPR 欧盟代表改为"暂无代表"

GDPR Art.27 要求非欧盟主体在面向欧盟用户提供服务时须指定 EU 代表。本工作室暂未指定,但原政策声明"已指定欧盟代表"与事实不符,可能被欧盟监管机构质疑。

修改位置:

  • 网页中文区 12.1 GDPR 子章节 — 「我们已指定欧盟代表,联系方式可通过本政策列明的邮箱获取」改为「我们暂未指定欧盟代表(GDPR Art.27 代表)。如有需要,您可通过本政策列明的邮箱与我们联系」
  • 网页英文区 XIII. International Data Protection GDPR 子章节同步表述为「We have not yet designated an EU Representative under GDPR Art.27. If needed, you may contact us via the email listed in this policy.」
  • App 内隐私政策简版新增「12. 国际数据保护」章节,欧盟代表表述与网页一致

3. 任务C:网页英文区补全 8 个缺失章节

英文区章节由 10 个补齐至 18 个(Zero-XIV),与中文区 17 个章节基本对齐(英文区多「IX. Deceased Person's Information」死者信息章节,是英文区原有保留项)。

新增英文章节 行号 对应中文章节
Zero. Definitions(由 <p> 改为 <h2>) 708 零、定义
II.5. Business Functions and Personal Information Mapping Table(含 14 行表格) 805-903 二点五、业务功能与个人信息映射表
VI. Cookie and Similar Technologies 1047 六、Cookie 及同类技术
VII. Third-Party SDKs(含 SDK 表格) 1049 七、第三方SDK
VII.5. Automated Decision-Making 1079 七点五、自动化决策
VIII.5. Personal Information Security Incident Response 1105 八点五、个人信息安全事件处置
X.5. Personal Information Protection Impact Assessment 1142 九点五、个人信息保护影响评估
XIII. International Data Protection(含 13.1 GDPR/13.2 CCPA/13.3 COPPA) 1186 十二、国际数据保护

章节号顺延:原 VI→VIII、VII→IX、VIII→X、IX→XI、X→XII、XI→XIV,所有子章节号(6.x→8.x、7.x→9.x、8.x→10.x、11.x→14.x)同步顺延。

翻译质量:严格保留 HTML 标签结构(<h2>/<h3>/<p>/<ul>/<li>/<table>/<span class="highlight">),表格(<table><thead><tbody>)严格保留。翻译符合法律文书风格。

4. 任务D:App 内隐私政策简版补全为详版

App 内 privacy_policy_page.dart 章节由 10 章补全至 17 章,与网页详版章节结构对齐(用户选择"补全章节保持简版"方案,不引入表格 widget)。

新增章节 内容摘要
0. 定义 9 个术语定义(个人信息/敏感信息/处理者/匿名化/去标识化等)
2.5 业务功能与个人信息映射表 5 项业务功能 × 个人信息映射(纯文本,网页详版含表格)
7. 第三方 SDK 当前未集成声明 + 未来集成承诺
7.5 自动化决策 个性化推荐说明 + 退出权 + 禁止用户画像承诺
8.5 个人信息安全事件处置 5 步应急响应(72h 评估/通知/报告/记录 3 年)
9.5 个人信息保护影响评估 5 种触发情形 + 评估内容 + 3 年保留
12. 国际数据保护 GDPR/CCPA/COPPA 简版,欧盟代表声明为"暂无代表"

保持现有 _buildSection + 纯文本 UI 风格,不引入表格 widget。文件头注释按规范更新。隐私政策正文"最后更新日期"保持 2026年5月7日 不变(用户要求)。

5. 涉及文件

  • lib/l10n/types/t_about.dart — 新增 entityInfoMenu/entityInfoMenuDesc 字段(构造/字段/toMap/fromMap 四处)
  • lib/l10n/languages/*.dart — 14 个语言文件补全 entityInfoMenu/entityInfoMenuDesc 翻译
  • lib/features/profile/presentation/about_page.dart — _LegalSection 新增主体信息菜单项 + _showEntityInfoDialog 弹窗 + _entityLine 渲染辅助方法
  • lib/features/settings/presentation/privacy/privacy_policy_page.dart — 章节补全(0/2.5/7/7.5/8.5/9.5/12)+ 文件头更新
  • docs/toolsapi/public/agreements/privacy-policy.html — 英文区补全 8 章节 + 章节号顺延 + GDPR 欧盟代表表述修正(中英两处)
  • CHANGELOG.md

6. 验证

  • flutter analyze lib/l10n/languages/ lib/l10n/types/t_about.dart lib/features/profile/presentation/about_page.dart lib/features/settings/presentation/privacy/privacy_policy_page.dart — No issues found!(8.2s)
  • 网页版通过 SFTP 上传至 https://tools.wktyl.com/agreements/privacy-policy.html,curl 验证新增章节已上线

7. 不足与建议

  • App 内隐私政策简版补全后,表格(如业务功能映射表)用纯文本代替,信息密度低于网页版。如未来需要更丰富展示,可考虑用 Table widget 重构
  • 网页英文区比中文区多「IX. Deceased Person's Information」章节(英文区原有保留),未来可考虑中文区也补这一章
  • 关于页弹窗内容仍为硬编码中英对照,未来如需深度多语言,可提取到 t_about.dart 字段


[v6.132.0] - 2026-06-26

新增(隐私政策披露 D-U-N-S 编号 + 主体信息章节 — 适配全球上架合规)

背景

工作室已取得邓白氏码D-U-N-S Number: 586261192App 计划在 Apple App Store / Google Play 全球上架。原隐私政策App 内 + 网页版仅披露公司名、统一社会信用代码、ICP 备案缺少国际通用的企业身份标识不利于海外监管机构、合作方与用户进行主体身份核验。GDPR 第 13/14 条要求"数据控制者"身份清晰披露D-U-N-S 作为全球企业唯一标识可显著提升合规性并降低审核争议。

1. App 内隐私政策页privacy_policy_page.dart

  • 在「8. 政策更新」与「9. 联系我们」之间新增「9. 主体信息」章节
  • 原「9. 联系我们」顺延为「10. 联系我们」
  • 「9. 主体信息」披露主体名称中英、经营别称DBA、D-U-N-S 编号、统一社会信用代码、注册地址(中英)、所属行业、隐私事务联系邮箱
  • 数据源Dun & Bradstreet 官网 + 工商注册信息
  • 文件头注释按规范更新「更新时间 / 上次更新内容」
  • 隐私政策正文"最后更新日期"保持 2026年5月7日 不变(用户要求)

2. 网页版隐私政策privacy-policy.html

  • 中文区:在「十、联系我们」前插入「十、主体信息」;原「十、联系我们」顺延为「十一、联系我们」;原「十一、国际数据保护」顺延为「十二、国际数据保护」,其子章节 11.1/11.2/11.3 同步顺延为 12.1/12.2/12.3
  • 英文区在「IX. Contact Us」前插入「IX. Entity Information」原「IX. Contact Us」顺延为「X. Contact Us」原「X. Legal Application and Dispute Resolution」顺延为「XI. Legal Application and Dispute Resolution」其子章节 10.1/10.2 同步顺延为 11.1/11.2
  • footer在「统一社会信用代码」与「ICP 备案号」之间新增 D-U-N-S 一行;地址统一更新为 D-U-N-S 官网注册地址中国云南省红河哈尼族彝族自治州弥勒市朋普镇朋普社区朋肖路49号 邮编652301
  • DATA 对象:新增 duns 字段(中英);更新 contact 地址为 D-U-N-S 官网注册地址(中英);英文公司名由原"…Weifengbao…"修正为 D-U-N-S 官网登记的"Mile Pengpu Town Micro Storm Network Technology Studio"
  • switchLang 函数:新增 footer-duns 元素的同步更新逻辑
  • 联系我们章节的"通信地址"同步更新为 D-U-N-S 官网注册地址(中英),保证整篇文档地址一致性

3. 关键决策与发现

  • 地址不一致问题:原 footer 与「联系我们」中填写的"云南省昆明市西山区滇池度假区碧鸡街道车家壁513号"与 D-U-N-S 官网登记的注册地址(红河州弥勒市朋普镇)不符。统一社会信用代码 92532526MA6PCX153W 中的 532526 行政区划码对应弥勒市,印证 D-U-N-S 官网地址为工商注册地址。本次以 D-U-N-S 官网地址为准统一全文,避免 Apple/Google 审核时主体信息核对出现偏差
  • 法定代表人字段移除初版主体信息含「法定代表人李振阳Zhenyang Li」字段应要求移除App 内 + 网页中英三处均已删除)。隐私政策主体信息聚焦"组织身份"而非"自然人身份",更符合数据最小化原则
  • 英文公司名修正:原 DATA.en.company 为"Mile City Pengpu Town Weifengbao Network Technology Studio",与 D-U-N-S 官网登记"Mile Pengpu Town Micro Storm Network Technology Studio"不一致。本次以 D-U-N-S 官网为准修正,确保 Apple Developer Program 主体核验通过

4. 合规建议(供后续维护参考)

  • App Store Connect:在 App 信息 → "开发者信息"处填写 D-U-N-S 586261192确保与隐私政策披露一致
  • Google Play Console:在"应用内容 → 隐私政策"URL 提交本页面,主体信息保持一致
  • 欧盟 GDPR 代表:当前"国际数据保护"章节声明已指定欧盟代表,但未具体披露代表身份。若目标用户含欧盟且无实体,建议后续在主体信息或国际数据保护章节明确 EU 代表身份与联系方式GDPR Art.27
  • CCPA"请勿出售"入口:当前声明"不出售个人信息"已合规;若后续商业模式变更需设立专门"请勿出售我的个人信息"链接
  • 关于页同步:建议检查 App 内「关于」页面t_about.dart是否同步展示 D-U-N-S保持多端一致本次未涉及留待后续

涉及文件

  • lib/features/settings/presentation/privacy/privacy_policy_page.dart新增「9. 主体信息」章节 + 章节顺延 + 文件头更新)
  • docs/toolsapi/public/agreements/privacy-policy.html(中文区/英文区新增「主体信息」章节 + 章节顺延 + footer 加 D-U-N-S + DATA 加 duns 字段 + 地址统一为 D-U-N-S 官网注册地址 + 英文公司名修正 + switchLang 加 footer-duns 同步)
  • CHANGELOG.md


[v6.131.0] - 2026-06-26

新增(工作台仪表盘全面国际化 + 动态主题/样式 + 交互增强)

背景

工作台模式右栏默认面板 OverviewDashboard 存在 23 处硬编码中文(问候语/区块标题/快捷操作标签/空状态/统计单位),不支持多语言;未消费 AppThemeExtensionfontScale/fontWeight 动态样式;动画 duration 硬编码不响应无障碍 reduceAnimations 降级;问候语在 build 内取 DateTime.now().hour,跨午时停留不刷新;favoriteState.total 等字段缺空指针防护。

1. 新增翻译模块 TDashboard

  • 新建 lib/l10n/types/t_dashboard.dart — 定义 TDashboard 类型27 个字段覆盖:时段问候语(5)、问候区(1)、今日推荐(4)、快捷操作(9)、最近浏览(2)、数据统计(6),含 toMap/fromMap/fallback 回退
  • lib/l10n/types/t_root.dart — 注入 dashboard 字段(构造函数/字段/toMap/fromMap 四处)
  • lib/l10n/types/t.dart — 导出 t_dashboard.dart
  • 14 语言文件补全 dashboard: TDashboard(...) 段落zh_CN/en 手写zh_TW/ja/ko/de/it/es/fr/pt/ru/ar/bn/hi 12 种补全,T.withFallback 自动回退英语

2. 重构 overview_dashboard.dart

  • ConsumerStatefulWidget + Timer:每分钟校验小时变更,跨午时(12:00)/傍晚(18:00)/深夜(22:00)自动刷新问候语与图标,dispose 取消定时器
  • 全文案多语言ref.watch(translationsProvider) 接入23 处硬编码替换为 t.dashboard.xxx
  • 动态主题/样式:字号统一 × ext.fontScale 缩放,正文字重跟随 ext.fontWeightGlassContainer 自动消费 cardStyleId/cornerRadiusId/glassBlurMultiplier
  • 触觉反馈:快捷操作/最近浏览点击加 HapticFeedback.selectionClick()
  • 骨架屏:今日推荐加载中(homeState.isLoading && recommends.isEmpty)显示 Shimmer 占位,深浅色自适应
  • 无障碍降级:响应 generalSettingsProvider.reduceAnimations,动画 duration 降为 Duration.zeroAppIcon.animate 关闭,SlideAnimation.verticalOffset 归零
  • 空指针防护authState.user?.signinDays ?? 0streakDays 单位用 db.streakDayUnit 拼接i18n
  • 作者引用 i18n'$db.authorPrefix${sentence.author ?? db.anonymousAuthor}'author 空字符串回退佚名

3. 举一反三(附带发现 → 已同步修复)

  • t_root.darttoMap() 缺少 'quickCard': quickCard.toMap()(现有 bug导致 T.withFallbackquickCard 模块失效——非中文/英语语言的 quickCard 空字段无法回退英语。本次已补上该键,并审查 t_settings_advanced 的 5 个 impeller 翻译键v6.129.0 新增)的 toMap/fromMap 完整性,确认无遗漏
  • translation_io_service.dartimportFromJson 构造 T(...) 缺少 dashboard 参数v6.130.0 给 T 加 required this.dashboard 后未同步更新,会导致编译错误)。本次已补上 dashboard: fallback.dashboard,参照 quickCard 的处理模式dashboard 属于非用户可编辑导出模块,直接用 fallback
  • 设计说明tToMap/exportAllTranslations 是"导出用户可编辑翻译"方法,设计上只含 nav/common/profile/settings/note/beta/submit/studyPlan/correction/leisure 9 个核心模块,不含 quickCard/dashboard——这是预期行为无需改动
  • 覆盖率检测自动包含translation_coverage.dart 通过 zhCN.toMap() 自动遍历所有 sectiontoMap 补全 quickCard 键后,覆盖率报告会自动包含 quickCard 模块的字段统计

涉及文件

  • lib/l10n/types/t_dashboard.dart(新增)
  • lib/l10n/types/t_root.dartlib/l10n/types/t.dart(注入导出 + 修复 toMap 漏写 quickCard 键)
  • lib/l10n/translation_io_service.dart(修复 importFromJson 的 T 构造缺 dashboard 参数)
  • lib/l10n/languages/*.dart14 个语言文件补全 dashboard 段落)
  • lib/app/layout/overview_dashboard.dart(重构)
  • CHANGELOG.md

---***

[v6.130.0] - 2026-06-26

新增macOS 权限动态申请 — 替代 permission_handler_apple 无 macOS 实现的问题)

背景macOS 端权限无法动态申请

  • Issue: permission_handler_apple 9.4.9 仅支持 iOS无 macOS 实现。此前 macOS 端权限管理页面直接返回 granted,用户点击"请求权限"按钮不会弹出系统授权对话框,实际授权发生在首次访问资源时由系统自动触发(被动模式)。用户无法在权限管理页面主动触发授权。
  • 方案: 新建 PermissionManager.swift 原生权限管理器,通过 apps.xy.xianyan/macos.app MethodChannel 暴露给 Flutter实现 macOS 原生权限动态申请。
  • 支持的权限:
    权限 原生 API 状态查询 请求方式
    相机 AVFoundation AVCaptureDevice.authorizationStatus(for: .video) AVCaptureDevice.requestAccess(for: .video)
    麦克风 AVFoundation AVCaptureDevice.authorizationStatus(for: .audio) AVCaptureDevice.requestAccess(for: .audio)
    相册 Photos framework PHPhotoLibrary.authorizationStatus(for:) PHPhotoLibrary.requestAuthorization(for:)
    通知 UserNotifications UNUserNotificationCenter.getNotificationSettings UNUserNotificationCenter.requestAuthorization
  • 权限状态映射:
    • notDetermined → 未决定(可请求)
    • granted → 已授权(含 .authorized / .limited / .provisional / .ephemeral
    • permanentlyDenied → 已拒绝macOS 拒绝后不再次弹窗,需去系统设置)
    • restricted → 受限(如家长控制)
  • 实现:
    1. 新建 macos/Runner/PermissionManager.swift — 原生权限管理器AVFoundation/Photos/UserNotifications
    2. AppDelegate.swiftregisterAppChannel 中新增 3 个 MethodChannel 方法:
      • checkPermission — 查询权限状态(异步)
      • requestPermission — 请求权限(触发系统 TCC 弹窗)
      • openPermissionSettings — 打开系统设置 - 隐私与安全性
    3. macos/Runner.xcodeproj/project.pbxproj — 将 PermissionManager.swift 添加到 Xcode 项目
    4. MacosPlatformService 新增 checkPermission / requestPermission / openPermissionSettings 三个方法
    5. PermissionService 修改 macOS 分支:
      • checkStatus — 调用原生 checkPermission 查询 TCC 状态
      • requestPermission — 调用原生 requestPermission 触发系统弹窗(先显示说明对话框,用户确认后触发)
      • openSettings — 调用原生 openPermissionSettings 跳转系统设置
    6. AppPermission 枚举新增 macosPermissionName getter — 返回 macOS 原生权限名称映射
  • 举一反三:
    • macOS TCC 权限模型与 iOS 不同:一旦用户拒绝,再次调用 requestAccess 不会弹窗(需用户去系统设置重置)。因此 macOS 上 denied 映射为 permanentlyDenied
    • 通知权限是例外:可以多次请求(requestAuthorization 每次都会返回当前状态,但不弹窗)
    • UNUserNotificationCenter.getNotificationSettings 是异步的,统一所有权限查询为异步回调模式
  • 涉及文件:
    • macos/Runner/PermissionManager.swift(新增)
    • macos/Runner/AppDelegate.swift — channel handler 新增 3 个 case
    • macos/Runner.xcodeproj/project.pbxproj — 添加文件引用
    • lib/core/services/device/macos_platform_service.dart — 新增权限管理方法
    • lib/core/services/auth/permission_service.dart — macOS 分支改为调用原生 API

[v6.129.0] - 2026-06-26

🐛 修复macOS 渲染引擎 — Impeller 开关不生效 + x86 警告 + Apple Silicon 提示)

问题:通用设置中 Impeller 开关无论打开或关闭,实际渲染引擎始终是 Skia

  • Issue: 用户在「通用设置 → 高级 → Impeller 渲染引擎」切换开关并重启应用后,实际渲染引擎始终为 Skia开关完全失效
  • 根因: MainFlutterWindow.swiftawakeFromNib() 使用 setenv("FLUTTER_ENGINE_SWITCH_0", ...) 试图通过环境变量传递 --enable-impeller/--no-enable-impeller 给 Flutter 引擎,但 macOS 桌面 embedder (FlutterMacOS) 不读取 FLUTTER_ENGINE_SWITCH_<N> 环境变量(该机制仅适用于 mobile embedder iOS/Android。同时 Info.plist 中的 FLTEnableImpeller key 已被早期版本移除,引擎无任何信号可读取,只能走 SDK 默认值SkiacurrentImpellerEnabled 缓存的是预期值而非实际值,进一步掩盖了问题,导致 UI 显示与引擎实际状态不符
  • 方案: 改用 FlutterDartProject + commandLineArguments 方式传递命令行参数,这是 macOS 桌面 embedder 唯一可靠的引擎开关控制方式,命令行参数优先级高于 Info.plist 的 FLTEnableImpeller 与 SDK 默认值
  • 实现:
    1. MainFlutterWindow.awakeFromNib() — 移除 setenv("FLUTTER_ENGINE_SWITCH_0", ...),改为:
      let dartProject = FlutterDartProject()
      dartProject.commandLineArguments = [impellerArg]
      let flutterViewController = FlutterViewController(project: dartProject)
      
    2. 保留 currentImpellerEnabled 静态变量缓存当前引擎实际运行状态(修复后此值与引擎实际状态一致)
    3. 默认值策略不变Apple Silicon 默认开启 ImpellerIntel Mac 默认关闭Metal 驱动有渲染资源累积 bug
  • 举一反三:
    • FLUTTER_ENGINE_SWITCH_<N> 环境变量机制仅适用于 mobile embedderiOS/Android桌面 embeddermacOS/Windows/Linux应使用 FlutterDartProject.commandLineArguments 或 Info.plist 的 FLTEnableImpeller key
    • 引擎开关的"实际运行状态"应通过引擎 API 查询,不能直接复用"预期值"作为缓存,否则会掩盖开关不生效的问题
    • Info.plist 中移除 FLTEnableImpeller 后必须确保有运行时替代方案(命令行参数 / FlutterDartProject否则引擎走 SDK 默认值
  • 涉及文件:
    • macos/Runner/MainFlutterWindow.swiftawakeFromNib() 改用 FlutterDartProject.commandLineArguments
    • macos/Runner/AppDelegate.swift — 注释同步更新(实际逻辑未变)

增强x86 端开启 Impeller 前增加警告对话框

  • Issue: Intel Mac (x86_64) 上 Metal 驱动有渲染资源累积 bug开启 Impeller 可能导致色差/字体割裂/闪烁。用户在不知情情况下开启 Impeller 可能造成体验问题
  • 方案: 在 _onImpellerToggle(value) 中检测架构,若为 x86_64 且 value == true,先弹出二次确认警告对话框,用户确认后才写入设置;用户取消则恢复开关状态
  • 实现:
    1. 新增 _showX86ImpellerWarningDialog(T t) 方法 — 返回 Future<bool>,用户确认返回 true取消返回 false
    2. 对话框包含警告图标(橙色三角形)+ 标题 + 详细描述(说明 Intel Mac 上的风险)+ 取消/仍要开启 两个按钮
    3. 用户取消时通过 setState 恢复 _impellerEnabled = false,不写入 UserDefaults
  • Apple Silicon 提示: 在重启对话框中新增 arm64 架构专属提示卡片(蓝色背景 + sparkles 图标),说明"Apple Silicon 上 Impeller 基于 Metal 性能更好,推荐开启"
  • 新增翻译键5 个,覆盖全部 14 种语言):
    • impellerX86WarningTitle — Intel Mac 兼容性警告标题
    • impellerX86WarningDesc — 警告描述(说明风险 + Apple Silicon 推荐使用 Skia
    • impellerX86WarningConfirm — 仍要开启
    • impellerX86WarningCancel — 取消
    • impellerAppleSiliconTip — Apple Silicon 推荐开启提示
  • 涉及文件:
    • lib/features/settings/presentation/general/general_settings_page.dart_onImpellerToggle / _showX86ImpellerWarningDialog / _buildImpellerDialogContent
    • lib/l10n/types/t_settings_advanced.dart — 新增 5 个字段 + toMap + fromMap
    • lib/l10n/languages/*.dart — 14 种语言全部添加新键

[v6.128.0] - 2026-06-26

🐛 修复macOS 运行时 — permission_handler MissingPluginException + WebRTC 构建冲突)

问题一permission_handler_apple 无 macOS 实现 — 权限管理页点击报错App Store 2.1(a) 直接原因)

  • Issue: macOS 端权限管理页点击「相册」「麦克风」「相机」请求时抛出 MissingPluginException(No implementation found for method checkPermissionStatus on channel flutter.baseflow.com/permissions/methods),点击「去设置」按钮同样报错。这是 v6.127.0 未覆盖的运行时问题,是 App Store 审核被拒 Guideline 2.1(a) 的直接原因
  • 根因: permission_handler_apple 9.4.9pubspec.yaml 仅声明 ios 平台,无 macOS 实现
    flutter:
      plugin:
        implements: permission_handler
        platforms:
          ios:                          # ⚠️ 仅 ios无 macos
            pluginClass: PermissionHandlerPlugin
    
    • permission_handler_apple-9.4.9/ 目录下只有 ios/,无 macos/
    • macOS 端 GeneratedPluginRegistrant.swift 不注册 PermissionHandlerApplePlugin
    • 调用 Permission.camera.status / Permission.photos.request() / openAppSettings() 均抛出 MissingPluginException
  • 方案: macOS sandbox 下权限由 entitlement + Info.plist 用法说明 自动管理,系统在首次访问受保护资源时弹出授权对话框(由 OS 触发,不由 App 调用)。permission_service.dart 添加 macOS 早返回逻辑,跳过 permission_handler 调用
  • 实现:
    1. checkStatus() — macOS 端直接返回 granted,避免调用未注册的方法通道
    2. requestPermission() — macOS 端直接返回 true,权限由系统 sandbox + entitlement 自动管理
    3. openSettings() — 新增 macOS 原生跳转:Process.run('open', ['x-apple.systempreferences:com.apple.preference.security?Privacy']),打开「系统设置 > 隐私与安全性」
    4. _showSettingsDialog / _showDeniedDialog — 将 openAppSettings() 调用改为 openSettings(),确保 macOS 端「去设置」按钮可用
    5. checkStatus() / requestPermission() 新增 on MissingPluginException 兜底Linux 等无 permission_handler 实现的桌面端视为已授权
  • 举一反三:
    • Flutter 联邦插件federated plugin的平台实现可能只覆盖部分平台使用前需检查 pub-cache 中实际包的 pubspec.yaml 平台声明
    • macOS sandbox 下权限模型与 iOS 不同iOS 需 App 主动调用 request()macOS 由 OS 在首次访问时自动弹出entitlement 是「App 级授权」OS 弹框是「用户级授权」
    • MissingPluginException 不应仅靠 try-catch 静默吞掉,需在入口处按平台显式短路,否则权限管理页状态显示为「未决定」具有误导性
  • 涉及文件:
    • lib/core/services/auth/permission_service.dartcheckStatus / requestPermission / openSettings / _showSettingsDialog / _showDeniedDialog

问题二flutter_webrtc 1.4.0 与 macOS WebRTC-SDK 144.7559.09 版本冲突

  • Issue: macOS pod install 报错 CocoaPods could not find compatible versions for pod "WebRTC-SDK"Podfile.lock 锁定 144.7559.09,但 flutter_webrtc 1.4.0 的 macOS podspec 依赖 144.7559.01.01 版本)
  • 根因: commit 667f3e49 添加本地 macos/WebRTC-SDK.podspec.json 声明 .09 版本Intel Mac 渲染修复补丁),但 flutter_webrtc 保持在 1.4.0pins .01),两者冲突
  • 方案: 升级 flutter_webrtc 1.4.0 → 1.5.2(其 macOS podspec 已对齐声明 s.dependency 'WebRTC-SDK', '144.7559.09'
  • 验证: flutter analyze 通过,screen_share_page.dart / webrtc_service.dart / screen_share_provider.dart 无 API 变更
  • 鸿蒙端: 本地包 packages/flutter_webrtcv1.4.0-ohos.1)无法直接升级,待后续同步到 1.5.2-ohos;两端 pubspec 独立互不影响
  • 涉及文件:
    • pubspec.yamlflutter_webrtc: ^1.4.0^1.5.2
    • pubspec.macos.yaml — 同上
    • pubspec.ohos.yaml — 更新 flutter_webrtc 注释(远程端已升至 1.5.2
    • pubspec.lock — flutter_webrtc sha256 更新
    • iOS_macOS_Developer_Guide.md — 差异对照表更新 + 新增 §2.8.9 flutter_webrtc 特殊包说明 + 新增 §2.8.10 permission_handler_apple macOS 缺失实现说明

[v6.127.0] - 2026-06-26

🐛 修复macOS App Store 审核被拒 — Guideline 2.4.5(i) / 2.1(a)

macOS 审核三大问题修复 — entitlement 配置 + 权限管理全平台适配

: 本条目覆盖 entitlement 配置与权限卡片平台过滤;运行时 MissingPluginException 修复见 v6.128.0。

  • Issue: macOS 版本 6.6.25 (2606260) 提交 App Store 被拒,三条审核意见:
    1. Guideline 2.4.5(i) — 声明了未使用的 entitlementfiles.downloads.read-onlyfiles.downloads.read-writenetwork.server
    2. Guideline 2.4.5(i) — 有功能但缺对应 entitlement相机缺 com.apple.security.device.camera,位置缺 com.apple.security.personal-information.location
    3. Guideline 2.1(a) — 在权限管理页点击「相册&存储」「麦克风」请求时显示错误信息
  • 根因:
    1. Release.entitlements / DebugProfile.entitlements 声明了 files.downloads.* 但全代码库无 getDownloadsDirectory 调用(字体下载用的是 getApplicationDocumentsDirectory),属于声明未使用
    2. 扫码 / 拍照 / OCR / 语音录制 / 语音转文字功能在共享代码中无平台守卫macOS 端实际可用,但未声明 device.camera / device.audio-input / personal-information.photos-library entitlementInfo.plistNSCameraUsageDescription / NSMicrophoneUsageDescription 用法说明
    3. permission_service.dartisPlatformRelevant 对 macOS 无任何过滤鸿蒙端有过滤macOS 落到 return true),导致权限管理页在 macOS 展示相机/相册/位置/附近设备/麦克风卡片;点击请求时因 entitlement + Info.plist 双缺,permission_handler 在 sandbox 下请求失败弹出错误对话框
    4. 位置GPS实际全平台未使用仅 IP 定位 + 手动文本输入),却展示位置权限卡片具有误导性
  • 方案:
    1. macOS entitlements移除未用的 files.downloads.*;新增 device.camera / device.audio-input / personal-information.photos-library;保留 network.serverLocalSend 文件传输本地服务器必需)
    2. macOS Info.plist:新增 NSCameraUsageDescription / NSMicrophoneUsageDescription 用法说明
    3. 重写 isPlatformRelevant 为全平台适配macOS/Windows/Linux/Web 各自过滤;位置卡片仅移动端展示(桌面端/Web 只用 IP 定位);附近设备仅移动端;相册仅 macOS + 移动端Windows/Linux/Web 用文件选择器)
    4. 新增 localServer 虚拟权限卡片(仅桌面端展示),对应 network.server entitlement向用户透明声明 LocalSend 文件传输本地服务器能力
  • 实现:
    1. entitlementsDebugProfile.entitlements + Release.entitlements 同步修改:移除 2 个 downloads 键,新增 3 个 device/photos 键
    2. Info.plist — 新增相机 / 麦克风用法说明(中文)
    3. permission_service.dartAppPermission 枚举新增 localServer 虚拟权限;label/description/usageScenes/denialImpact 4 个 switch 补全 caseisPlatformRelevant 重写为「特殊权限单独处理 + 鸿蒙/桌面/Web/移动端分支」结构
    4. l10nt_settings_permission.dart 新增 permLocalServer* 4 字段(构造/字段/toMap/fromMap14 个语言文件新增 4 条翻译
  • 举一反三:
    • entitlement 应遵循「最小权限集」原则,声明即需有对应功能,否则触发审核质疑;后续新增 entitlement 必须同步在权限管理页向用户声明用途
    • 跨平台权限过滤不能只覆盖单一平台(鸿蒙),所有桌面端 / Web 都需显式过滤,否则同一 bug 会在其他平台复现
    • macOS sandbox 下 permission_handler 依赖 entitlement + Info.plist usage description 双重配置才能弹系统授权框,缺一即失败
  • 审核回复要点(提交 App Store Connect 时使用):
    • network.server 用于 LocalSend 局域网文件传输(HttpServer.bind / ServerSocket.bind),见 localsend_service.dart / tcp_socket_service.dart
    • 已移除未使用的 files.downloads.* entitlement
    • 已补全相机 / 麦克风 entitlement 与用法说明,权限管理页请求功能正常
  • 涉及文件:
    • macos/Runner/DebugProfile.entitlements — 移除 downloads新增 camera/audio-input/photos-library
    • macos/Runner/Release.entitlements — 同上
    • macos/Runner/Info.plist — 新增 NSCameraUsageDescription / NSMicrophoneUsageDescription
    • lib/core/services/auth/permission_service.dart — 新增 localServer 枚举 + 全平台 isPlatformRelevant
    • lib/l10n/types/t_settings_permission.dart — 新增 permLocalServer 4 字段
    • lib/l10n/languages/*.dart14 个语言文件)— 新增 permLocalServer 4 条翻译

[v6.126.0] - 2026-06-25

🐛 修复(键盘事件)

RawKeyboard 断言错误修复

  • Issue: [ERR-MQSQKCXW] Flutter framework 断言失败:'event is! RawKeyDownEvent || _keysPressed.isNotEmpty',出现在 raw_keyboard.dart 第 863 行
  • 根因: Flutter 框架已知 bug#109677#116530)。RawKeyboard(已废弃)与 HardwareKeyboard 同时接收键盘事件,当修饰键标志未正确设置时,RawKeyboard 内部 _keysPressed 为空,收到 RawKeyDownEvent 时断言失败
  • 方案: 在 main()WidgetsFlutterBinding.ensureInitialized() 之后添加 HardwareKeyboard.instance.addHandler((_) => false) 处理器,确保键盘事件正确传播
  • 涉及文件:
    • lib/main.dart — 第 58-63 行新增 HardwareKeyboard 处理器

[v6.125.0] - 2026-06-25

🐛 修复macOS 双标题栏)

macOS 窗口"双标题栏"问题 — 隐藏系统红黄绿灯按钮

  • Issue: macOS 端软件窗口显示两个窗口栏红黄绿灯那一栏上方还有一栏Flutter 自绘的 DesktopWindowTitleBar),需去掉系统的红黄绿灯栏
  • 根因:
    1. Flutter 侧 DesktopWindowTitleBar 已自绘 macOS 风格的红黄绿三圆点按钮(_MacOSTrafficButton
    2. 原生侧 awakeFromNib 仅设置了 titlebarAppearsTransparent = true / titleVisibility = .hidden / fullSizeContentView未隐藏系统 standardWindowButton
    3. 隐藏系统按钮的逻辑仅写在 setDarkMode 方法中(MainFlutterWindow.swift 第 402-404 行),而 setDarkModeMacosPlatformService.syncTheme 调用时有去重机制(if (_themeInitialized && _lastIsDark == isDark) return),仅主题变化时触发一次
    4. 因此应用启动初期、全屏退出后、主题未变化时,系统红黄绿灯按钮始终可见,与 Flutter 自绘标题栏形成"双标题栏"
  • 方案: 提取公共方法 hideSystemTrafficButtons(of:),在三个时机统一隐藏系统红黄绿灯按钮
  • 实现:
    1. 新增 hideSystemTrafficButtons(of window: NSWindow? = nil) — 隐藏 closeButton/miniaturizeButton/zoomButton;参数为 nil 时遍历所有窗口(兼容多窗口),指定窗口时仅操作该窗口(启动时性能更优)
    2. awakeFromNib — 在设置透明属性后立即调用 hideSystemTrafficButtons(of: self)确保启动时即隐藏Intel Mac 也调用,因 Flutter 自绘标题栏在所有桌面平台一致显示)
    3. setDarkMode — 将原内联的三行 standardWindowButton?.isHidden = true 替换为 hideSystemTrafficButtons() 调用,消除重复代码
    4. handleFullScreenExit — 全屏退出后重新调用 hideSystemTrafficButtons(of: self),防止系统重置按钮可见性
  • 举一反三:
    • 此前 setDarkMode 承担了"主题切换 + 隐藏按钮"两个职责,按钮隐藏依赖主题切换时机触发,属于隐式依赖。现提取为独立方法后,职责清晰,可在任意时机显式调用
    • 类似的"启动时未初始化"问题排查方向:所有依赖 Dart 侧 MethodChannel 回调才执行的原生初始化逻辑,都应在 awakeFromNib 中有默认值或主动初始化,避免通道未就绪时显示异常
  • 涉及文件:
    • macos/Runner/MainFlutterWindow.swift — 新增 hideSystemTrafficButtons(of:) 方法;awakeFromNib/setDarkMode/handleFullScreenExit 三处调用;更新文件头注释

[v6.124.0] - 2026-06-25

增强Impeller 开关对话框 — 架构/实时状态/业务提示)

Impeller 开关对话框增强 — 显示 CPU 架构与引擎实时运行状态

  • Issue: 通用设置页 Impeller 开关对话框存在三个问题
    1. "稍后重启"仅关闭对话框,无业务提示和状态反馈
    2. "立即重启"只关闭应用未启动新实例(NSApp.terminate 执行过快)
    3. 对话框缺少 CPU 架构和引擎实时运行状态信息
  • 方案:
    1. 原生侧新增 currentImpellerEnabled 静态缓存 — 区分"用户设置值"UserDefaults可能已修改未生效和"引擎实际运行状态"(应用启动时固定)
    2. 新增 getImpellerRunningStatus channel — 返回当前引擎实际是否在用 Impeller
    3. 新增 getCpuArchitecture channel — 返回 arm64/x86_64,用于对话框显示
    4. restartApp 改进 — 添加 800ms 延迟、错误检查、日志;先启动新实例再终止当前实例
    5. 对话框增强 — 显示三行状态:当前架构 / 当前引擎(实际运行)/ 重启后
    6. 稍后重启增强 — 关闭对话框后显示 Toast 提示"设置已保存,重启后生效"
    7. 副标题增强 — 用户修改设置未重启时,副标题显示"待重启生效"标记
  • 实现:
    1. MainFlutterWindow.swift: 新增 currentImpellerEnabled 静态变量,在 awakeFromNib 中缓存引擎实际运行状态
    2. AppDelegate.swift: 新增 getImpellerRunningStatus/getCpuArchitecture channel 方法;restartApp 添加延迟+错误检查+日志
    3. MacosPlatformService.dart: 新增 getImpellerRunningStatus()/getCpuArchitecture() 方法;restartApp() 改为返回 Future<bool>
    4. general_settings_page.dart: 新增 _impellerPendingRestart/_cpuArch/_impellerRunning 状态变量;_loadImpellerEnabled 并行加载三个值;重写 _onImpellerToggle 增强对话框;新增 _buildImpellerDialogContent/_buildStatusRow 辅助方法
    5. general_settings_sections.dart: 新增 impellerPendingRestart 参数,副标题动态显示"待重启生效"标记
    6. i18n: 为 14 个语言文件添加 5 个新翻译键impellerSavedToast/impellerPendingRestart/impellerDialogArch/impellerDialogRunning/impellerDialogAfterRestart
  • 涉及文件:
    • macos/Runner/MainFlutterWindow.swift — 新增 currentImpellerEnabled 静态缓存
    • macos/Runner/AppDelegate.swift — 新增 getImpellerRunningStatus/getCpuArchitecture channel改进 restartApp
    • lib/core/services/device/macos_platform_service.dart — 新增 getImpellerRunningStatus/getCpuArchitecture 方法
    • lib/features/settings/presentation/general/general_settings_page.dart — 增强对话框显示架构+实时状态,稍后重启显示 Toast
    • lib/features/settings/presentation/general/general_settings_sections.dart — 副标题显示待重启标记
    • lib/l10n/types/t_settings_advanced.dart — 新增 5 个翻译键定义
    • lib/l10n/languages/*.dart — 14 个语言文件添加新翻译键

[v6.123.0] - 2026-06-25

🐛 修复Intel Mac 渲染色差/字体割裂)

Impeller 渲染引擎开关 — 默认值策略 + 立即重启 + i18n

  • Issue: Intel Mac 上页面跳转动画闪烁、字体模糊割裂、色差(前几次跳转正常,累积后出现)
  • 根因: Flutter Impeller 渲染引擎在 Intel Mac 的 Metal 驱动上有渲染资源累积 bug导致色差/字体割裂
  • 验证方法:
    1. 原生 AppKit demo纯 Cocoa 渲染)排除硬件问题 — 字体显示正常,无异常色彩
    2. 禁用 Impeller 后问题消失,确认根因在 Impeller
  • 方案: 默认值策略 — Apple Silicon 开启 Impeller性能更好Intel Mac 关闭(避免色差)。用户可在「通用设置 → 高级」中手动覆盖,修改后需重启应用生效
  • 实现:
    1. Info.plist: 移除 FLTEnableImpeller 声明,由原生代码根据用户设置动态控制
    2. MainFlutterWindow.swift:
      • 手动创建 FlutterDartProject,通过 KVC 设置 commandLineArguments--enable-impeller/--no-enable-impeller
      • 命令行参数优先级高于 Info.plist可动态控制 Impeller 开关
      • 新增 shouldEnableImpeller() 方法,通过 object(forKey:) 判断用户是否已显式设置:
        • 已设置:返回用户设置的值
        • 未设置首次启动Apple Silicon 默认开启Intel Mac 默认关闭
    3. AppDelegate.swift:
      • 新增 getImpellerEnabled/setImpellerEnabled MethodChannel 方法
      • getImpellerEnabled 使用 getImpellerEnabledWithDefault() 保持与 shouldEnableImpeller() 逻辑一致
      • 新增 restartApp 原生方法 — 通过 NSWorkspace.openApplication 启动新实例后 NSApp.terminate 终止当前实例
    4. MacosPlatformService.dart: 新增 getImpellerEnabled()/setImpellerEnabled()/restartApp() 方法
    5. general_settings_sections.dart: 高级分组新增 Impeller 开关(仅 macOS使用 i18n 翻译键
    6. general_settings_page.dart: 加载/切换 Impeller 状态,切换后弹出重启提示对话框(含"立即重启"和"稍后重启"两个按钮)
    7. i18n: 为 14 个语言文件添加 8 个 Impeller 翻译键zh_cn/zh_tw/en/ja/ko/fr/de/es/pt/ru/ar/hi/bn/it
  • 涉及文件:
    • macos/Runner/Info.plist — 移除 FLTEnableImpeller
    • macos/Runner/MainFlutterWindow.swift — 手动创建引擎传递命令行参数 + 默认值策略
    • macos/Runner/AppDelegate.swift — Impeller MethodChannel + restartApp 方法
    • lib/core/services/device/macos_platform_service.dart — Impeller 开关 + restartApp 方法
    • lib/features/settings/presentation/general/general_settings_sections.dart — 高级分组 Impeller 开关
    • lib/features/settings/presentation/general/general_settings_page.dart — 加载/切换 Impeller 状态 + 重启对话框
    • lib/l10n/types/t_settings_advanced.dart — 新增 8 个 Impeller 翻译键定义
    • lib/l10n/languages/*.dart — 14 个语言文件添加 Impeller 翻译

[v6.122.0] - 2026-06-24

🔧 维护pro_image_editor 版本锁定)

1. pro_image_editor 版本锁定为 12.4.4

  • Issue: 本地暂存修改将 pro_image_editor 从 12.4.4 改为 ^12.4.8,与远程代码产生冲突
  • 原因: 12.5.x 版本与 Flutter 3.33 运行时不兼容,需锁定到 12.4.4 确保稳定性
  • 修复:
    • pubspec.macos.yaml: 锁定 pro_image_editor: 12.4.4
    • pubspec.ohos.yaml: 锁定 pro_image_editor: 12.4.4
    • 注释说明 12.5.x 与 Flutter 3.33 运行时不兼容
  • 涉及文件: pubspec.macos.yaml, pubspec.ohos.yaml

[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._updateBackdropViewremoveFromSuperview
    • 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 != nilpassthroughViewHandler.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.pbxprojknownRegions 仅包含 enBase
  • 修复:
    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.stringsPBXVariantGroupPBXFileReference
      • 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 的 objectIdMainMenu.xib 声明顺序一致,跳过 separatorItem
      • 新增 assignMenuItemIdentifiers() 方法,在 awakeFromNib 中递归遍历 NSApp.mainMenu,按顺序将 objectId 赋值给对应 menuItem.identifier
    2. 原生侧 — 切换菜单语言MainFlutterWindow.swift
      • 新增 setMenuLanguage(languageId:) 方法:
        • 根据 languageId 解析 lproj 目录名(systemBundle.preferredLocalizations(from:) 跟随系统;zh-CN/zh-Hanszh-Hanszh-TW/zh-Hantzh-Hanten/ja/ko → 对应 lproj
        • 通过 Bundle.main.path(forResource:ofType:forLocalization:) 加载对应语言的 MainMenu.strings[String: String]
        • 递归遍历 NSApp.mainMenu,根据 menuItem.identifierXIB 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/setMenuLanguageawakeFromNib 调用 assignMenuItemIdentifiers
    • lib/core/services/device/macos_platform_service.dart — 新增 setMenuLanguage 静态方法
    • lib/features/settings/providers/general_settings_provider.dartsetLanguage 调用 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 = AutomaticexportArchive 阶段会自动使用 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.dartthinFramework 的逐架构验证修复snapshot 未随源码更新重新编译)
  • 修复:
    1. 项目配置macos/Runner.xcodeproj/project.pbxprojRelease 配置 ARCHSarm64 改为 $(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 设置的调用,仅保留主题相关的 overrideMacOSBrightnessNSVisualEffectView 操作
    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 — 跳过首次窗口特效同步

🔧 维护pubspec.yaml 同步鸿蒙端模板)

1. pubspec.yaml 版本号与依赖同步鸿蒙端模板

  • Issue: pubspec.yaml 版本落后6.6.22+2606213且头部注释错误标注为"鸿蒙端模板",与 pubspec.ohos.yaml 模板6.6.25+2606241不同步
  • 原因: 拉取 git 代码后未重新生成 pubspec.yaml,导致主文件与鸿蒙端模板版本号不一致
  • 修复:
    • 基于 pubspec.ohos.yaml 模板重新生成 pubspec.yaml
    • 版本号升级6.6.22+2606213 → 6.6.25+2606241
    • 头部注释修正为"主 pubspec.yaml基于鸿蒙端模板生成"
    • 所有依赖项、本地包引用、dependency_overrides 完全对齐 pubspec.ohos.yaml
    • 保留 msix dev_dependency 和 msix_config 配置Windows 端 Microsoft Store 打包专用)
  • 涉及文件: pubspec.yaml
  • 验证: git diff --no-index pubspec.ohos.yaml pubspec.yaml 确认差异仅为 msix 配置和头部注释

[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 到右栏嵌套 NavigatorrightPanelStackProvider),页面显示在右栏并支持栈式返回
    • 非工作台模式或全屏路由仍走 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: 输入预选词发送后,页面没有回复诗词
  • 原因:
    • _buildMessagespoetrySessions 历史列表构建消息,发送后新诗词未正确显示
    • _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: 相关诗词卡片中的收藏和分享按钮点击无任何响应
  • 原因: _buildActionChipGestureDetector 缺少 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.animationIntensitydurationMultiplier<=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.dartlib/features/home/providers/home_interaction_mixin.dartlib/features/home/presentation/widgets/home_sentence_list_section.dart

7. 创作卡片/编辑此句返回主页动画

  • Issue: 从编辑器返回主页时无重新聚焦动画
  • 修复: 新增 markReturnedFromEditor() 方法,清空入场动画历史,编辑器返回后句子卡片重新播放入场动画
  • 涉及文件: lib/features/home/providers/home_provider.dartlib/features/home/presentation/providers/sentence_detail_sheet.dartlib/features/home/presentation/panels/sentence_detail_actions.dart

[v6.113.0] - 2026-06-23

🐛 修复(句子广场循环加载 + 热力图重绘 + 入场动画增强)

1. 句子广场骨架卡死修复任务6

  • Issue: 主页句子广场滑到底部时显示骨架无法滑动,列表不增长
  • 根因: fetchNewSentences 去重耗尽后使用 fallback 但 hasMore=true,导致骨架持续显示但无新数据追加;_buildListBottomhasMore=false 时返回空 SizedBox.shrink()
  • 修复:
    • home_feed_mixin.dart: 去重3轮后无新数据时重置 allSeenIds/allSeenTexts保留最近20条避免立即重复用本次返回数据继续填充列表实现循环加载
    • home_sentence_list_section.dart: _buildListBottomhasMore=false 且非离线时,显示"已经看完所有内容"提示 + 重新加载按钮(带入场动画)
    • 新增 resetAndReload() 方法清空已见集合从第1页重新拉取
  • 涉及文件: lib/features/home/providers/home_feed_mixin.dartlib/features/home/providers/home_provider.dartlib/features/home/presentation/widgets/home_sentence_list_section.dartlib/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.dartlib/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.dartlib/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.dartlib/features/settings/presentation/workbench/workbench_settings_page.dartlib/features/settings/presentation/general/general_settings_pickers.dartlib/core/layout/workbench/workbench_layout.dartlib/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.dartlib/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,菜单无法应用尺寸
  • 根因:
    • _applySizetargetH.clamp(minH, screen.height - 16) 要求 lowerLimit <= upperLimit
    • _screenWorkArea 异步初始化未完成时,回退到 MediaQuery.sizeOf(context),而 MediaQuery 在桌面端返回的是窗口尺寸(可能很小,如 300×200
    • screen.height - 16 < 360(即窗口高度 < 376clamp(360.0, <360) 抛出 Invalid argument(s): 360.0
  • 修复:
    • 使用 math.max(minW, screen.width - 16) 确保 clamp 上限不小于下限
    • _applySize 中若 _screenWorkArea 为 nullawait _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 互斥,触发断言
    • ColumnmainAxisSize 默认为 MainAxisSize.max,在无界约束下尝试扩展到无限大小
  • 修复:
    • Expanded 改为 Flexible(默认 FlexFit.loose),在有界约束下可扩展填充剩余空间,在无界约束下可自然收缩到子组件固有大小
    • 显式设置 ColumnmainAxisSize: 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 无法布局
  • 修复:
    • 移除 OverflowBoxdouble.infinity,改用屏幕对角线 × 1.5 作为有限容器尺寸(保证旋转后仍覆盖全屏)
    • 移除 Containerwidth/height: double.infinity,改用 Padding 避免无限尺寸传播
  • 涉及文件: lib/shared/widgets/beta_testing_overlay.dart

2. BetaTestingOverlay ParentData 传递失败Positioned 必须直接挂在 Stack 下)

  • Issue: macOS 运行时抛出 Incorrect use of ParentDataWidgetPositioned 无法找到 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 可用宽度时产生溢出
  • 修复:
    • 作者和标题 TextFlexible 包裹,添加 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.dartlib/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.dartStack 顶层叠加)
    • 修改 lib/editor/pages/editor/editor_page.dartProEditorPage 与加载态均叠加)
    • 修改 lib/features/source/presentation/source_page.dartCupertinoPageScaffold 外层 Stack 叠加)
    • 修改 lib/features/widget/presentation/widget_management_page.dartCupertinoPageScaffold 外层 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 次仍可能不匹配
  • 修改:
    • 新增内存缓存 _tagCache5 分钟 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,内容变化时触发过渡
    • 新增 transitionBuilderFadeTransition + 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.dartPoetryTagSelector

2. 标签组合选择

  • Issue: 只能选择单个标签
  • 修改:
    • 支持同时选择多个标签(如「秋+雨」组合筛选)
    • 已选标签显示在搜索框下方,支持点击取消/清除全部
    • PoetryState.selectedTagsString? 改为 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.dartPoetryCalendarSheet

8. 统一聊天记录系统

  • Issue: poetryHistorychatRecords 两套独立系统,数据冗余
  • 修改:
    • 合并为统一的 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.dart586 行)拆分出 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 miniXianyan 保持不变
    • 中文字体名(宋体/楷体等)翻译为对应语言的字体描述
  • 验证: 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.dart921 行)— 主入口,保留状态字段、回调、构建方法
    • quick_card_layouts.dart705 行)— QuickCardStackedLayout + QuickCardSplitLayout 两种布局
    • quick_card_bars.dart349 行)— QuickCardNavBar + QuickCardActionBar + QuickCardSplitTopBar
    • quick_card_state_logic.dart194 行)— 纯逻辑:stateToJson/stateFromJson/applyPreset/applyAutoPalette/resetState/resetHomeStyle
    • quick_card_dialogs.dart362 行)— 文字编辑对话框 + 更多操作 Sheet + 结果提示
  • 验证: flutter analyze 9 个文件全部通过No issues found!

2. 多语言全量接入TQuickCard 翻译类型)

  • Issue: Sheet 内所有用户可见文案为硬编码中文,不支持多语言切换
  • 修复
    • 新增 lib/l10n/types/t_quick_card.dart525 行)— 定义 100+ 翻译键
    • T 根类新增 quickCard 字段,集成到 T.fromMap/toMap
    • zh_cn.dart / en.dart 新增 quickCard: TQuickCard(...) 完整翻译
    • 主 Sheet 新增 _t getterTQuickCard 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.dartif (pu.isOhos) { AppToast.showInfo('敬请期待'); return; } 限制
    • 移除 sentence_detail_sheet.dart 中相同的限制逻辑
    • 清理未使用的 platform_utils 导入
    • 鸿蒙端现在可以直接跳转到 /editor?text=... 进入编辑器
  • 依据: /editor 路由在鸿蒙端正常注册(route_registry.dart:1130-1138EditorPage 无平台限制
  • 文件
    • 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 行)— 模板管理底部面板
    • 数据模型 QuickCardTemplatekey/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 色横条,持久化到 KvStoragequick_card_recent_colors 键)
    • 吸管取色:image_picker 选图 → package:image 解码 → 3x3 网格采样取平均色
    • 颜色选择器对话框升级28 色预设 + 最近使用 + HSL 三滑块
    • 7 预设色 + 自定义入口 + 吸管取色按钮
  • 修复 CupertinoIcons eyedropper 未定义:改为 Icons.colorizeMaterial 图标)

3. 壁纸库接入

  • Issue: 背景图片选择路径单一,仅支持从相册选择,未支持从项目内置壁纸库选择
  • 修复
    • 新增 quick_card_background_section.dart~560 行)— 独立背景选择模块
    • _WallpaperLibrarySheet 底部面板来源切换栏12 源)+ 网格 + 长按预览
    • 复用 features/templatewallpaperProvider + WallpaperPreviewSheet
    • 背景选择行新增"从壁纸库选择"入口
    • 网络壁纸 URL 通过 imagePath 字段存储

4. 文件拆分quick_card_style_sections.dart 917行 → 430行

  • Issue: quick_card_style_sections.dart 文件过大,违反单一职责
  • 修复
    • _BackgroundRow + _GradientAngleChipquick_card_background_section.dart
    • _ColorRowquick_card_color_section.dart
    • QuickCardStyleSection 新增 onAutoPalette 参数
    • 移除 image_pickerlogger 导入(已迁移到子文件)

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+ 学习计划重构预告 + 闲情逸致"免费"改"平价" + 纠错页全面多语言