feat: persist timetable and validate confirmed imports

This commit is contained in:
Codex
2026-10-12 23:18:51 +08:00
parent ae8e347e49
commit 808af007a2
13 changed files with 852 additions and 0 deletions
+49
View File
@@ -0,0 +1,49 @@
import 'dart:io';
import 'dart:convert';
import 'snapshot_store.dart';
import '../domain/app_snapshot.dart';
class FileSnapshotStore extends SnapshotStore {
FileSnapshotStore(this.directory);
final Directory directory;
File get _file => File('${directory.path}/hepan_snapshot.json');
File get _backup => File('${directory.path}/hepan_snapshot.bak');
Future<AppSnapshot> _read(File file) async {
final value = jsonDecode(await file.readAsString());
if (value is! Map<String, dynamic>) throw const FormatException('保存文件损坏');
return AppSnapshot.fromJson(value);
}
@override
Future<AppSnapshot?> load() async =>
await _file.exists() ? await _read(_file) : null;
@override
Future<void> save(AppSnapshot snapshot) async {
await directory.create(recursive: true);
final text = jsonEncode(snapshot.toJson());
// Validate before touching the last successfully saved version.
AppSnapshot.fromJson(jsonDecode(text) as Map<String, dynamic>);
if (await _file.exists()) {
try {
await _read(_file);
await _file.copy(_backup.path);
} on FormatException {
/* Keep an existing valid backup. */
}
}
final temporary = File('${_file.path}.tmp');
await temporary.writeAsString(text, flush: true);
await temporary.rename(_file.path);
}
@override
Future<AppSnapshot> restoreBackup() async {
if (!await _backup.exists()) throw StateError('没有可恢复的备份');
final previous = await _read(_backup);
final temporary = File('${_file.path}.tmp');
await temporary.writeAsString(jsonEncode(previous.toJson()), flush: true);
await temporary.rename(_file.path);
return previous;
}
}