mirror of
https://gitlab.com/comunic/comunicmobile
synced 2024-12-30 14:58:52 +00:00
122 lines
3.1 KiB
Dart
122 lines
3.1 KiB
Dart
|
import 'dart:convert';
|
||
|
import 'dart:io';
|
||
|
|
||
|
import 'package:comunic/constants.dart';
|
||
|
import 'package:path/path.dart' as path;
|
||
|
import 'package:path_provider/path_provider.dart';
|
||
|
|
||
|
/// Base serialization helper
|
||
|
///
|
||
|
/// @author Pierre Hubert
|
||
|
|
||
|
abstract class SerializableElement<T> extends Comparable<T> {
|
||
|
Map<String, dynamic> toJson();
|
||
|
}
|
||
|
|
||
|
abstract class BaseSerializationHelper<T extends SerializableElement> {
|
||
|
/// List cache
|
||
|
List<T> _cache;
|
||
|
|
||
|
/// The name of the type of data to serialise
|
||
|
String get type;
|
||
|
|
||
|
/// Parse an json entry into a [T] object
|
||
|
T parse(Map<String, dynamic> m);
|
||
|
|
||
|
/// Get the file where data should be stored
|
||
|
Future<File> _getFilePath() async {
|
||
|
final dir = await getApplicationDocumentsDirectory();
|
||
|
final targetDir =
|
||
|
Directory(path.join(dir.absolute.path, SERIALIZATION_DIRECTORY));
|
||
|
|
||
|
targetDir.create(recursive: true);
|
||
|
|
||
|
return File(path.join(targetDir.absolute.path, type));
|
||
|
}
|
||
|
|
||
|
/// Load the cache
|
||
|
Future<void> _loadCache() async {
|
||
|
if (_cache != null) return;
|
||
|
|
||
|
try {
|
||
|
final file = await _getFilePath();
|
||
|
|
||
|
if (!await file.exists()) return _cache = List();
|
||
|
|
||
|
final List<dynamic> json = jsonDecode(await file.readAsString());
|
||
|
_cache = json.cast<Map<String, dynamic>>().map(parse).toList();
|
||
|
|
||
|
_cache.sort();
|
||
|
} catch (e, s) {
|
||
|
print("Failed to read serialized data! $e => $s");
|
||
|
_cache = List();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/// Save the cache to the persistent memory
|
||
|
Future<void> _saveCache() async {
|
||
|
final file = await _getFilePath();
|
||
|
await file.writeAsString(jsonEncode(
|
||
|
_cache.map((e) => e.toJson()).toList().cast<Map<String, dynamic>>()));
|
||
|
}
|
||
|
|
||
|
/// Get the current list of elements
|
||
|
Future<List<T>> getList() async {
|
||
|
await _loadCache();
|
||
|
return List.from(_cache);
|
||
|
}
|
||
|
|
||
|
/// Set a new list of conversations
|
||
|
Future<void> setList(List<T> list) async {
|
||
|
_cache = List.from(list);
|
||
|
await _saveCache();
|
||
|
}
|
||
|
|
||
|
/// Insert new element
|
||
|
Future<void> insert(T el) async {
|
||
|
await _loadCache();
|
||
|
_cache.add(el);
|
||
|
_cache.sort();
|
||
|
await _saveCache();
|
||
|
}
|
||
|
|
||
|
/// Insert new element
|
||
|
Future<void> insertMany(List<T> els) async {
|
||
|
await _loadCache();
|
||
|
_cache.addAll(els);
|
||
|
_cache.sort();
|
||
|
await _saveCache();
|
||
|
}
|
||
|
|
||
|
/// Check if any entry in the last match the predicate
|
||
|
Future<bool> any(bool isContained(T t)) async {
|
||
|
await _loadCache();
|
||
|
return _cache.any((element) => isContained(element));
|
||
|
}
|
||
|
|
||
|
/// Check if any entry in the last match the predicate
|
||
|
Future<T> first(bool filter(T t)) async {
|
||
|
await _loadCache();
|
||
|
return _cache.firstWhere((element) => filter(element));
|
||
|
}
|
||
|
|
||
|
/// Replace an element with another one
|
||
|
Future<void> insertOrReplaceElement(bool isToReplace(T t), T newEl) async {
|
||
|
await _loadCache();
|
||
|
|
||
|
// Insert or replace the element
|
||
|
_cache.where((element) => !isToReplace(element)).toList();
|
||
|
_cache.add(newEl);
|
||
|
|
||
|
_cache.sort();
|
||
|
await _saveCache();
|
||
|
}
|
||
|
|
||
|
/// Remove elements
|
||
|
Future<void> removeElement(bool isToRemove(T t)) async {
|
||
|
await _loadCache();
|
||
|
_cache.removeWhere((element) => isToRemove(element));
|
||
|
await _saveCache();
|
||
|
}
|
||
|
}
|