背景
由于生成缩略图需要耗费很多流量(图片需要下载原图生成,视频需要流媒体提取帧),不再默认自动重生成丢失的缩略图,改为可控的策略。
实现内容
1. 设置页面选项
在设置页面添加两个独立开关:
- 自动生成图片缩略图:缩略图丢失时自动重新生成,会耗费流量
- 自动生成视频缩略图:缩略图丢失时自动重新生成,会耗费流量
配置存储在 SharedPreferences,key 为:
auto_gen_missing_image_thumbsauto_gen_missing_video_thumbs
2. 浏览时的行为
修改 fetchOrGenerateThumbnail 函数,增加 autoGenImage 和 autoGenVideo 参数:
- 先查本地缓存
- 尝试从后端获取
- 如果不存在,根据配置决定是否自动重新生成
3. 文件菜单生成缩略图选项
在文件操作菜单中添加”生成缩略图”选项:
单文件(图片/视频):
- 点击后弹窗提示会耗费流量
- 确认后强制重新生成(先删除旧的再生成)
文件夹:
- 两个勾选项:
- 递归包含子文件夹
- 仅生成缺失的缩略图
- 勾选后动态更新统计数量
- 分别显示图片和视频数量
- 两个按钮:生成图片、生成视频
4. 删除提示
在缩略图文件夹(/.thumbs/)下删除文件时,弹窗增加流量警告: “删除后再次生成缩略图会耗费网络/S3传输流量”
技术细节
图片缩略图生成流程
- 调用
deleteThumbnailAPI 删除后端缩略图 - 清除本地缓存
- 调用
getThumbnailWithInfoAPI,后端自动下载原图并生成缩略图 - 保存到本地缓存
视频缩略图生成流程
- 获取流媒体 URL
- 前端调用 VideoThumbnailService 提取帧
- Android: MediaMetadataRetriever
- Desktop: FFmpeg
- 调用
uploadThumbnailAPI 上传 - 保存到本地缓存
统计文件夹内媒体文件
Future<({int imageCount, int videoCount, List<FileMetadata> files})>
_countMediaFiles({
required String folderPath,
required bool recursive,
required bool onlyMissing,
}) async {
// 递归:f.path.startsWith(folderPath)
// 非递归:f.path == folderPath
// 仅缺失:检查本地缓存是否存在
}修改的文件
lib/core/state/app_state.dart- 配置变量和持久化lib/ui/settings_page.dart- 设置开关 UIlib/ui/widgets/file_tiles.dart- fetchOrGenerateThumbnail 函数lib/ui/chat_page.dart- 调用点更新lib/ui/widgets/file_action_sheet.dart- onGenerateThumbnail 回调lib/core/services/file_operation_service.dart- 完整实现
关键逻辑修复
问题1:图片缩略图不会强制重新生成
后端 downloadThumbnail 如果缩略图已存在会直接返回,不会重新生成。 修复:先调用 deleteThumbnail 再获取。
问题2:视频缩略图生成失败计数不准
生成失败但不抛异常时,successCount 仍然增加。 修复:生成失败时抛出异常。
问题3:文件夹只处理直接子文件
修复:添加”递归包含子文件夹”勾选项。
问题4:无法跳过已有缩略图
修复:添加”仅生成缺失的缩略图”勾选项,勾选时检查本地缓存。