156 lines
4.5 KiB
Dart
156 lines
4.5 KiB
Dart
|
|
import 'dart:async';
|
||
|
|
import 'dart:convert';
|
||
|
|
import 'dart:developer';
|
||
|
|
import 'dart:io';
|
||
|
|
import 'dart:typed_data';
|
||
|
|
|
||
|
|
import 'package:flutter/widgets.dart';
|
||
|
|
import 'package:mnemo_cards_common/mnemo_cards_common.dart';
|
||
|
|
import 'package:path_provider/path_provider.dart';
|
||
|
|
import 'package:shared_preferences/shared_preferences.dart';
|
||
|
|
|
||
|
|
import '../../di/locator.dart';
|
||
|
|
|
||
|
|
// persist
|
||
|
|
class PackCacheManager {
|
||
|
|
late final SharedPreferences _sharedPreferences;
|
||
|
|
|
||
|
|
PackCacheManager();
|
||
|
|
|
||
|
|
Future<void> init() async {
|
||
|
|
_sharedPreferences = await SharedPreferences.getInstance();
|
||
|
|
}
|
||
|
|
|
||
|
|
Future<CardPackDto> loadPackFromCache(
|
||
|
|
String packId, {
|
||
|
|
bool withCardImages = true,
|
||
|
|
}) async {
|
||
|
|
log('Loading from cache ${packId}');
|
||
|
|
try {
|
||
|
|
final packDir = await _packDirectory(packId);
|
||
|
|
final packFile = File('${packDir.path}/pack.json');
|
||
|
|
if (!packFile.existsSync()) {
|
||
|
|
log('Pack file not exist');
|
||
|
|
return throw Exception('Pack file not exist');
|
||
|
|
}
|
||
|
|
var pack = CardPackDto.fromJson(
|
||
|
|
jsonDecode(packFile.readAsStringSync()),
|
||
|
|
);
|
||
|
|
if (withCardImages) {
|
||
|
|
Map<String, MemoryImage> images = {};
|
||
|
|
log('Cards ${packId}: ${pack.cards.length}');
|
||
|
|
if (pack.cards.isNotEmpty) {
|
||
|
|
log('Loading cards ${packId}');
|
||
|
|
for (final dto in pack.cards) {
|
||
|
|
final file = File('${packDir.path}/images/${dto.id}');
|
||
|
|
if (file.existsSync()) {
|
||
|
|
try {
|
||
|
|
images[dto.id.toString()] =
|
||
|
|
MemoryImage(await file.readAsBytes());
|
||
|
|
} catch (e) {
|
||
|
|
throw Exception('Cant load pack $packId $e');
|
||
|
|
}
|
||
|
|
} else {
|
||
|
|
log('Cant load card ${dto.id} from $packId, skiping');
|
||
|
|
continue;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
log('Pack loaded ${packId}');
|
||
|
|
locator.imagesHolder.setPackImages(images);
|
||
|
|
}
|
||
|
|
return pack;
|
||
|
|
} catch (e, s) {
|
||
|
|
log('Cant load from cache ${packId} ${e} ${s}');
|
||
|
|
deletePack(packId);
|
||
|
|
rethrow;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
Future<List<String>> _updateSavedPacks() async {
|
||
|
|
final packsDir =
|
||
|
|
Directory('${(await getApplicationDocumentsDirectory()).path}/packs');
|
||
|
|
List<String> savedPackIds = [];
|
||
|
|
if (packsDir.existsSync()) {
|
||
|
|
for (final packDir in packsDir.listSync()) {
|
||
|
|
if (File('${packDir.path}/pack.json').existsSync()) {
|
||
|
|
savedPackIds.add(packDir.path.split('/').last);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
_sharedPreferences.setStringList('packs', savedPackIds);
|
||
|
|
return savedPackIds;
|
||
|
|
}
|
||
|
|
|
||
|
|
Future<List<CardPackDto>> loadAllPacks() async {
|
||
|
|
final ids = await _updateSavedPacks();
|
||
|
|
final List<CardPackDto> packs = [];
|
||
|
|
for (final id in ids) {
|
||
|
|
try {
|
||
|
|
final pack = await loadPackFromCache(id, withCardImages: false);
|
||
|
|
packs.add(pack);
|
||
|
|
} catch (e) {
|
||
|
|
log('Pack $id doesnt exist anymore');
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return packs;
|
||
|
|
}
|
||
|
|
|
||
|
|
Future<void> deletePack(String packId) async {
|
||
|
|
try {
|
||
|
|
final dir = await _packDirectory(packId);
|
||
|
|
dir.deleteSync(recursive: true);
|
||
|
|
} catch (e) {
|
||
|
|
log('Deletion failed $e');
|
||
|
|
}
|
||
|
|
_updateSavedPacks();
|
||
|
|
}
|
||
|
|
|
||
|
|
Future<Uint8List?> loadPackFile(String packId, String path) async {
|
||
|
|
final bytes =
|
||
|
|
File('${(await _packDirectory(packId)).path}/$path').readAsBytesSync();
|
||
|
|
return bytes;
|
||
|
|
}
|
||
|
|
|
||
|
|
Future<void> clearCache() async {
|
||
|
|
final saved = await _updateSavedPacks();
|
||
|
|
for (final p in saved) {
|
||
|
|
await deletePack(p);
|
||
|
|
}
|
||
|
|
await _sharedPreferences.remove('packs');
|
||
|
|
}
|
||
|
|
|
||
|
|
Future<void> savePack(CardPackDto dto,
|
||
|
|
{Map<String, MemoryImage>? images}) async {
|
||
|
|
log('Saving pack ${dto.id}');
|
||
|
|
final dir = await _packDirectory(dto.id);
|
||
|
|
final json = jsonEncode(dto);
|
||
|
|
log('Saving dto ${dto.id}');
|
||
|
|
File('${dir.path}/pack.json')
|
||
|
|
..createSync(recursive: true)
|
||
|
|
..writeAsStringSync(json);
|
||
|
|
|
||
|
|
if (images != null) {
|
||
|
|
log('Saving card images ${dto.id}');
|
||
|
|
final imageDir = Directory('${dir.path}/images');
|
||
|
|
if (imageDir.existsSync()) {
|
||
|
|
imageDir.deleteSync(recursive: true);
|
||
|
|
}
|
||
|
|
for (final card in dto.cards) {
|
||
|
|
final bytes = images[card.id.toString()]?.bytes;
|
||
|
|
if (bytes != null) {
|
||
|
|
File('${imageDir.path}/${card.id}')
|
||
|
|
..createSync(recursive: true)
|
||
|
|
..writeAsBytesSync(bytes);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
log('Saved ${dto.id}');
|
||
|
|
}
|
||
|
|
|
||
|
|
Future<Directory> _packDirectory(String id) async => Directory(
|
||
|
|
'${(await getApplicationDocumentsDirectory()).path}/packs/$id',
|
||
|
|
);
|
||
|
|
}
|