feat: persist timetable and validate confirmed imports
This commit is contained in:
@@ -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;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user