petsHero-AI/lib/features/gallery/gallery_upload_cover_store.dart
2026-03-31 09:42:49 +08:00

82 lines
2.6 KiB
Dart
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import 'dart:io';
import 'package:path_provider/path_provider.dart';
/// 生图流程创建任务后,按接口返回的 `tree`(任务 id将用户上传的压缩图存一份到本地
/// Gallery 在接口未返回封面 URL 时可用其作为卡片底图。
abstract final class GalleryUploadCoverStore {
static const String _subdir = 'gallery_upload_covers';
static const String _fileExt = '.jpg';
/// 本地封面最多保留时长,超时文件会在下次读/写前删除。
static const Duration maxRetention = Duration(hours: 25);
static Future<Directory> _directory() async {
final base = await getApplicationSupportDirectory();
final dir = Directory('${base.path}/$_subdir');
if (!await dir.exists()) {
await dir.create(recursive: true);
}
return dir;
}
static Future<Directory> _directoryAfterPurge() async {
final dir = await _directory();
await _purgeExpired(dir);
return dir;
}
static Future<void> _purgeExpired(Directory dir) async {
if (!await dir.exists()) return;
final now = DateTime.now();
try {
await for (final entity in dir.list(followLinks: false)) {
if (entity is! File) continue;
final name = entity.uri.pathSegments.last;
if (!name.endsWith(_fileExt)) continue;
final stat = await entity.stat();
if (now.difference(stat.modified) >= maxRetention) {
try {
await entity.delete();
} catch (_) {}
}
}
} catch (_) {}
}
static File _fileForTask(Directory dir, int taskId) =>
File('${dir.path}/$taskId$_fileExt');
/// [source] 一般为 [compressImageForUpload] 输出的待上传文件。
static Future<void> saveForTask(int taskId, File source) async {
if (taskId <= 0) return;
if (!await source.exists()) return;
final dir = await _directoryAfterPurge();
final dest = _fileForTask(dir, taskId);
await source.copy(dest.path);
}
static Future<String?> pathIfExists(int taskId) async {
if (taskId <= 0) return null;
final dir = await _directoryAfterPurge();
final f = _fileForTask(dir, taskId);
return await f.exists() ? f.path : null;
}
/// 仅查询 [ids] 中已有文件的 path用于列表刷新后一次性填充状态。
static Future<Map<int, String>> existingPathsForTaskIds(
Iterable<int> ids,
) async {
final dir = await _directoryAfterPurge();
final out = <int, String>{};
for (final id in ids) {
if (id <= 0) continue;
final f = _fileForTask(dir, id);
if (await f.exists()) {
out[id] = f.path;
}
}
return out;
}
}