data.dart 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  1. import 'package:flutter/material.dart';
  2. import 'package:puzzleweave/models/api_helper.dart';
  3. import 'package:puzzleweave/models/cached_request.dart';
  4. import 'package:puzzleweave/models/items.dart';
  5. import 'package:puzzleweave/persistence/persistence.dart';
  6. import 'package:logging/logging.dart';
  7. import 'package:puzzleweave/utils/utils.dart';
  8. final Logger _log = Logger('data.dart');
  9. class Data {
  10. final Persistence _persistence;
  11. ValueNotifier<List<Work>> completedWorks = ValueNotifier([]); // 已完成的图
  12. ValueNotifier<List<Work>> completedCollections = ValueNotifier([]); // 已完成的收藏图
  13. Data({required Persistence persistence}) : _persistence = persistence;
  14. Future<void> loadDataFromPersistence() async {
  15. // for test 为了测试合集完成动画
  16. // var works = _persistence.completedWorks;
  17. // works = works.sublist(0, works.length - 1);
  18. // _persistence.completedWorks = works;
  19. // _persistence.completedCollections = [];
  20. completedWorks.value = _persistence.completedWorks;
  21. completedCollections.value = _persistence.completedCollections;
  22. }
  23. // 完成某个作品调用此接口记录到存储中
  24. // !!! 改造点:接受 ListItem 和可选的耗时
  25. void workDone(ListItem item, {Duration? timeSpent}) {
  26. final newWork = Work.fromListItem(item, timeSpent: timeSpent);
  27. // 1. 记录作品完成
  28. final updatedWorks = [...completedWorks.value, newWork];
  29. completedWorks.value = updatedWorks;
  30. _persistence.completedWorks = updatedWorks; // 存储更新后的列表
  31. // 2. 核心新增:清除已完成作品的缓存
  32. _clearCompletedItemCache(item);
  33. }
  34. /// 清除已完成作品的缓存文件。
  35. void _clearCompletedItemCache(ListItem item) async {
  36. // 只有 RemoteItem 才会有需要清理的下载缓存
  37. if (item is RemoteItem) {
  38. _log.info('Work done for remote item ${item.id}. Attempting to clear cache at path: ${item.cachePath}');
  39. try {
  40. // 使用 cachePath 定义,并通过 localFile 找到实际的文件路径
  41. final file = await localFile(item.cachePath);
  42. if (await file.exists()) {
  43. await file.delete();
  44. _log.info('Successfully cleared cache file for ${item.id}');
  45. } else {
  46. _log.warning('Cache file not found for ${item.id} at path: ${item.cachePath}');
  47. }
  48. } catch (e) {
  49. _log.severe('Failed to clear cache for item ${item.id}, error: $e');
  50. }
  51. } else {
  52. _log.info('Work done for asset item ${item.id}. No network cache to clear.');
  53. }
  54. }
  55. // 获取当前的关卡index (基于已完成作品的数量)
  56. int get currentLevel => completedWorks.value.length;
  57. // 完成某个collection
  58. void collectionDone(ListItem item) {
  59. final newCollection = Work.fromListItem(item);
  60. final updatedCollections = [...completedCollections.value, newCollection];
  61. completedCollections.value = updatedCollections;
  62. _persistence.completedCollections = updatedCollections; // 存储更新后的列表
  63. }
  64. // 获取当前的合集index (基于已完成收藏的数量)
  65. int get currentCollectionIndex => completedCollections.value.length;
  66. CachedRequest? _latest;
  67. CachedRequest get latest {
  68. _latest ??= CachedRequest.fromUrl(
  69. ApiHelper.latestUri,
  70. transformFunction: (json) async {
  71. late List<ListItem> list;
  72. if (json['asset'] != null) {
  73. // from asset
  74. list = List<AssetItem>.from((json['data'] as Iterable).map((e) => AssetItem.fromJSON(e)));
  75. } else {
  76. // from remote
  77. list = List<RemoteItem>.from((json['data'] as Iterable).map((e) => RemoteItem.fromJSON(e)));
  78. }
  79. return list;
  80. },
  81. );
  82. return _latest!;
  83. }
  84. CachedRequest? _collection;
  85. CachedRequest get collection {
  86. _collection ??= CachedRequest.fromUrl(
  87. ApiHelper.collectionUri,
  88. transformFunction: (json) async {
  89. late List<ListItem> list;
  90. if (json['asset'] != null) {
  91. // from asset
  92. list = List<AssetItem>.from((json['data'] as Iterable).map((e) => AssetItem.fromJSON(e)));
  93. } else {
  94. // from remote
  95. list = List<RemoteItem>.from((json['data'] as Iterable).map((e) => RemoteItem.fromJSON(e)));
  96. }
  97. return list;
  98. },
  99. );
  100. return _collection!;
  101. }
  102. }