| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178 |
- import 'package:flutter/material.dart';
- import 'package:puzzleweave/models/api_helper.dart';
- import 'package:puzzleweave/models/cached_request.dart';
- import 'package:puzzleweave/models/items.dart';
- import 'package:puzzleweave/persistence/persistence.dart';
- import 'package:logging/logging.dart';
- import 'package:puzzleweave/utils/utils.dart';
- final Logger _log = Logger('data.dart');
- class Data {
- final Persistence _persistence;
- ValueNotifier<List<Work>> completedWorks = ValueNotifier([]); // 已完成的图
- ValueNotifier<List<Work>> completedCollections = ValueNotifier([]); // 已完成的收藏图
- Data({required Persistence persistence}) : _persistence = persistence;
- Future<void> loadDataFromPersistence() async {
- // for test 为了测试合集完成动画
- var works = _persistence.completedWorks;
- works = works.sublist(0, works.length - 1);
- _persistence.completedWorks = works;
- _persistence.completedCollections = [];
- // 1. 先初始化内置索引(独立、确定、不依赖缓存判断)
- await _initBuiltinRegistry();
- completedWorks.value = _persistence.completedWorks;
- completedCollections.value = _persistence.completedCollections;
- }
- /// 独立初始化内置图索引,确保无论网络/磁盘缓存如何,Asset 里的图都能被识别
- Future<void> _initBuiltinRegistry() async {
- try {
- _log.info('Initializing BuiltinRegistry from Asset...');
- // 直接读取资源文件,不走 CachedRequest 逻辑
- final latestData = await loadJSONFromAsset('assets/builtin/latest.json');
- if (latestData['data'] != null) {
- BuiltinRegistry.init(latestData['data']);
- _log.info('BuiltinRegistry initialized with ${latestData['total']} items.');
- }
- // 如果 collection.json 也有内置 ID 需要保护,也可以在这里 init
- // final collectionData = await loadJSONFromAsset('assets/builtin/collection.json');
- // BuiltinRegistry.init(collectionData['data']);
- } catch (e) {
- _log.severe('Failed to initialize BuiltinRegistry: $e');
- }
- }
- // 完成某个作品调用此接口记录到存储中
- // !!! 改造点:接受 ListItem 和可选的耗时
- void workDone(ListItem item, {Duration? timeSpent}) {
- final newWork = Work.fromListItem(item, timeSpent: timeSpent);
- // 1. 记录作品完成
- final updatedWorks = [...completedWorks.value, newWork];
- completedWorks.value = updatedWorks;
- _persistence.completedWorks = updatedWorks; // 存储更新后的列表
- // 2. 核心新增:清除已完成作品的缓存
- _clearCompletedItemCache(item);
- }
- /// 清除已完成作品的缓存文件。
- void _clearCompletedItemCache(ListItem item) async {
- // 删除进度状态json
- try {
- final file = await localFile(item.jsonPath);
- if (await file.exists()) {
- await file.delete();
- _log.info('Successfully cleared json cache file for ${item.id}');
- } else {
- _log.warning('json cache file not found for ${item.id} at path: ${item.jsonPath}');
- }
- } catch (e) {
- _log.severe('Failed to clear json cache for item ${item.id}, error: $e');
- }
- // 只有 RemoteItem 才会有需要清理的下载缓存
- if (item is RemoteItem) {
- _log.info('Work done for remote item ${item.id}. Attempting to clear cache at path: ${item.cachePath}');
- try {
- final file = await localFile(item.cachePath);
- if (await file.exists()) {
- await file.delete();
- _log.info('Successfully cleared cache file for ${item.id}');
- } else {
- _log.warning('Cache file not found for ${item.id} at path: ${item.cachePath}');
- }
- final tmpfile = await localFile('${item.cachePath}.tmp');
- if (await tmpfile.exists()) {
- await tmpfile.delete();
- _log.info('Successfully cleared cache tmp file for ${item.id}');
- }
- } catch (e) {
- _log.severe('Failed to clear cache for item ${item.id}, error: $e');
- }
- } else {
- _log.info('Work done for asset item ${item.id}. No network cache to clear.');
- }
- }
- // 获取当前的关卡index (基于已完成作品的数量)
- int get currentLevel => completedWorks.value.length;
- // 完成某个collection
- void collectionDone(ListItem item) {
- final newCollection = Work.fromListItem(item);
- final updatedCollections = [...completedCollections.value, newCollection];
- completedCollections.value = updatedCollections;
- _persistence.completedCollections = updatedCollections; // 存储更新后的列表
- }
- // 获取当前的合集index (基于已完成收藏的数量)
- int get currentCollectionIndex => completedCollections.value.length;
- CachedRequest? _latest;
- CachedRequest get latest {
- _latest ??= CachedRequest.fromUrl(
- ApiHelper.latestUri,
- transformFunction: (json) async {
- late List<ListItem> list;
- if (json['asset'] != null) {
- // from asset
- list = List<AssetItem>.from((json['data'] as Iterable).map((e) => AssetItem.fromJSON(e)));
- } else {
- // from remote
- list = List<RemoteItem>.from((json['data'] as Iterable).map((e) => RemoteItem.fromJSON(e)));
- }
- return list;
- },
- );
- return _latest!;
- }
- CachedRequest? _collection;
- CachedRequest get collection {
- _collection ??= CachedRequest.fromUrl(
- ApiHelper.collectionUri,
- transformFunction: (json) async {
- late List<ListItem> list;
- if (json['asset'] != null) {
- // from asset
- list = List<AssetItem>.from((json['data'] as Iterable).map((e) => AssetItem.fromJSON(e)));
- } else {
- // from remote
- list = List<RemoteItem>.from((json['data'] as Iterable).map((e) => RemoteItem.fromJSON(e)));
- }
- return list;
- },
- );
- return _collection!;
- }
- }
- // 内置图索引
- class BuiltinRegistry {
- static final Set<String> _builtinIds = {};
- // 在 App 启动(或 CachedRequest 加载内置数据时)调用
- static void init(List<dynamic> data) {
- _builtinIds.clear();
- for (var item in data) {
- if (item['_id'] != null) {
- _builtinIds.add(item['_id']);
- }
- }
- }
- static bool contains(String id) => _builtinIds.contains(id);
- }
|