session_store.dart 1.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253
  1. import 'dart:convert';
  2. import 'dart:io';
  3. import 'package:flutter/foundation.dart';
  4. import 'package:path_provider/path_provider.dart';
  5. /// 会话存档:Symja 定义 + 命令历史。
  6. ///
  7. /// 写入走「临时文件 + 改名」,保证原子性:写到一半被杀不会留下半个坏存档,
  8. /// 否则下次启动 JSON 解析失败就会丢掉全部变量。
  9. class SessionStore {
  10. static const _version = 1;
  11. /// 存档文件名。设置另存一个文件 —— 会话存档会被工具/控制台频繁重写,
  12. /// 混在一个文件里就意味着「存历史」和「存设置」要互相读改写。
  13. SessionStore({this.fileName = 'session.json'});
  14. final String fileName;
  15. Future<File> _file() async {
  16. final dir = await getApplicationDocumentsDirectory();
  17. return File('${dir.path}/$fileName');
  18. }
  19. /// 读存档。任何异常都当成「没有存档」返回 null —— 存档问题绝不能挡住启动。
  20. Future<Map<String, dynamic>?> load() async {
  21. try {
  22. final f = await _file();
  23. if (!f.existsSync()) return null;
  24. final decoded = jsonDecode(await f.readAsString());
  25. if (decoded is! Map<String, dynamic>) return null;
  26. if (decoded['version'] != _version) return null;
  27. return decoded;
  28. } catch (e) {
  29. debugPrint('读取存档失败,按空存档处理: $e');
  30. return null;
  31. }
  32. }
  33. Future<void> save(Map<String, dynamic> data) async {
  34. try {
  35. final f = await _file();
  36. final tmp = File('${f.path}.tmp');
  37. await tmp.writeAsString(
  38. jsonEncode(<String, dynamic>{'version': _version, ...data}),
  39. flush: true,
  40. );
  41. await tmp.rename(f.path);
  42. } catch (e) {
  43. debugPrint('写入存档失败: $e');
  44. }
  45. }
  46. }