import 'dart:async'; import 'dart:developer'; import 'package:mnemo_cards/di/locator.dart'; import 'package:mnemo_cards/features/packs/loading_packs_holder.dart'; import 'package:mnemo_cards/features/packs/pack_cache_manager.dart'; import 'package:mnemo_cards/features/packs/packs_api.dart'; import 'package:mnemo_cards/features/packs/preview_pack_holder.dart'; import 'package:mnemo_cards/managers/repository/repository.dart'; import 'package:mnemo_cards_common/mnemo_cards_common.dart'; import 'package:rxdart/rxdart.dart'; import 'pack_holder.dart'; class PackManager { final Repository _repository; final PacksApi _packsApi; final PackHolder _packHolder; final PreviewPackHolder _previewPackHolder; final LoadingPacksHolder _loadingPacksHolder; final PackCacheManager _cacheManager; PackManager( this._repository, this._packsApi, this._packHolder, this._previewPackHolder, this._loadingPacksHolder, this._cacheManager, ); Future init() async { final packs = await _cacheManager.loadAllPacks(); _packHolder.setPacksWithCards(packs.map((p) => p.id).toList()); // _repository.userStream.map((u) => u.packs).distinct().listen((packs) async { // final savedPacks = await savedPacksIds; // for (final p in packs) { // if (savedPacks.contains(p)) { // final loaded = await loadPackFromCache(p); // if (loaded.cards.isEmpty) { // await downloadPackById(p); // } // } else { // await downloadPackById(p); // } // } // }); } Stream getCardPackStream( CardPackPreviewDto preview, ) async* { final loadingDto = CardPackLoadingDto.fromPreviewDto(preview); final isAvailable = preview.isAvailable; final id = preview.id; if (isAvailable) { try { yield await _cacheManager.loadPackFromCache(id); } catch (err) { yield loadingDto; log('Cant load pack from cache, fetching pack', error: err); try { await locator.packUpdater.updatePackAndSaveImages(id); yield await _cacheManager.loadPackFromCache(id); } on Object catch (e, s) { log('Cant fetch pack', error: e, stackTrace: s); } } } else { yield loadingDto; final buyDto = await _packsApi.getPackBuy(id).catchError((_) => null); if (buyDto != null) { yield buyDto; _packHolder.removePackWithCards(id); } else { log('Buy dto is null, fetching pack'); try { await locator.packUpdater.updatePackAndSaveImages(id); yield await _cacheManager.loadPackFromCache(id); } on Object catch (e, s) { log('Cant fetch pack', error: e, stackTrace: s); } } } yield* Rx.combineLatest2( _packHolder.asStream .map( (state) => state.packsWithCards.firstWhereOrNull((packId) => packId == id), ) .asyncMap( (packId) async => packId == null ? null : await _cacheManager.loadPackFromCache(packId), ), _loadingPacksHolder.asStream .map((state) => state?.packs.firstWhereOrNull((p) => p.id == id)), (dto, isLoadingResponse) => isLoadingResponse ?? dto, ).whereNotNull(); } Future clearCache() async { _packHolder.clear(); await _cacheManager.clearCache(); } Stream?> get packsPreviewStream => _previewPackHolder.asStream .map((event) => event?.previewPacks) .whereNotNull() .distinct((prev, next) { if (prev.length != next.length) return false; for (int i = 0; i < prev.length; i++) { if (prev[i] != next[i]) return false; // if (prev[i].isAvailable != next[i].isAvailable) return false; // if (prev[i].id != next[i].id) return false; // if (prev[i].version != next[i].version) return false; // if (prev[i].price != next[i].price) return false; // if (prev[i].price != next[i].price) return false; // if (prev[i].cards != next[i].cards) return false; } return true; }); }