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
This commit is contained in:
Developer
2026-06-26 08:46:23 +08:00
parent 0c9faf30b7
commit 81ea0f60dc
20 changed files with 817 additions and 124 deletions

View File

@@ -6,6 +6,188 @@
***
## [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_cache``readlater_sync``chat_audio``chat_attachments``chat_trash``cloud_cache``file_transfer``fonts``backups`
- 迁移 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.xianyan``xianyan`
3. **Documents**:仅清理已知应用子目录(`image_cache``chat_audio``chat_attachments` 等 9 个),不删除根内容
4. 新增 `_safeClearDirContents()` 辅助方法,支持路径校验
#### 保留的使用点(用户可见文件)
以下使用点保留 `getApplicationDocumentsDirectory()`,因为存储的是用户可见文件:
- `data_management_export_mixin.dart`:数据导出 `.xypk` 文件(导出后通过 share_plus 分享,路径不重要临时文件)
#### backup_service.dart 备份迁移(补充)
**`lib/core/services/data/backup_service.dart`**
- `backupDirPath``safeAppDirPath`Documents改为 `safeAppDataPath`Application Support
- `getBackupList()` 兼容新旧两个路径:同时扫描 Application Support 和 Documents合并结果并按文件名去重
- 新增 `_scanBackupDir()` 私有方法,提取目录扫描逻辑
**`lib/core/utils/platform/path_provider_native.dart`**
- 修正迁移子目录列表:`backups``xianyan_backups`(与 `backup_service.dart``_backupDirName` 保持一致)
**`lib/features/settings/presentation/more_settings_page.dart`** 和
**`lib/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-sandbox``false``true`
#### 决策过程
启用 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 非沙盒模式)