mirror of
https://gitlab.com/comunic/comunicmobile
synced 2025-06-19 00:05:16 +00:00
Start conversation upgrade
This commit is contained in:
121
lib/helpers/serialization/base_serialization_helper.dart
Normal file
121
lib/helpers/serialization/base_serialization_helper.dart
Normal file
@ -0,0 +1,121 @@
|
||||
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();
|
||||
}
|
||||
}
|
@ -0,0 +1,50 @@
|
||||
import 'dart:collection';
|
||||
|
||||
import 'package:comunic/helpers/serialization/base_serialization_helper.dart';
|
||||
import 'package:comunic/lists/conversation_messages_list.dart';
|
||||
import 'package:comunic/models/conversation_message.dart';
|
||||
|
||||
/// Conversations serialization helper
|
||||
///
|
||||
/// @author Pierre Hubert
|
||||
|
||||
final HashMap<int, ConversationsMessagesSerializationHelper> _instances =
|
||||
HashSet() as HashMap<int, ConversationsMessagesSerializationHelper>;
|
||||
|
||||
class ConversationsMessagesSerializationHelper
|
||||
extends BaseSerializationHelper<ConversationMessage> {
|
||||
final int convID;
|
||||
|
||||
ConversationsMessagesSerializationHelper._(int convID)
|
||||
: convID = convID,
|
||||
assert(convID != null);
|
||||
|
||||
factory ConversationsMessagesSerializationHelper(int convID) {
|
||||
if (!_instances.containsKey(convID))
|
||||
_instances[convID] = ConversationsMessagesSerializationHelper._(convID);
|
||||
|
||||
return _instances[convID];
|
||||
}
|
||||
|
||||
@override
|
||||
ConversationMessage parse(Map<String, dynamic> m) =>
|
||||
ConversationMessage.fromJson(m);
|
||||
|
||||
@override
|
||||
String get type => "conv-messages-$convID";
|
||||
|
||||
Future<ConversationMessagesList> getList() async =>
|
||||
ConversationMessagesList()..addAll(await super.getList());
|
||||
|
||||
Future<void> insertOrReplace(ConversationMessage msg) async =>
|
||||
await insertOrReplaceElement((t) => t.id == msg.id, msg);
|
||||
|
||||
Future<void> remove(ConversationMessage msg) async =>
|
||||
await removeElement((t) => t.id == msg.id);
|
||||
|
||||
/// Insert or replace a list of messages
|
||||
Future<void> insertOrReplaceAll(List<ConversationMessage> list) async {
|
||||
for (var message in list)
|
||||
await insertOrReplaceElement((t) => t.id == message.id, message);
|
||||
}
|
||||
}
|
@ -0,0 +1,32 @@
|
||||
import 'package:comunic/helpers/serialization/base_serialization_helper.dart';
|
||||
import 'package:comunic/lists/conversations_list.dart';
|
||||
import 'package:comunic/models/conversation.dart';
|
||||
|
||||
/// Conversations serialization helper
|
||||
///
|
||||
/// @author Pierre Hubert
|
||||
|
||||
var _cache;
|
||||
|
||||
class ConversationsSerializationHelper
|
||||
extends BaseSerializationHelper<Conversation> {
|
||||
/// Singleton
|
||||
factory ConversationsSerializationHelper() {
|
||||
if (_cache == null) _cache = ConversationsSerializationHelper._();
|
||||
return _cache;
|
||||
}
|
||||
|
||||
ConversationsSerializationHelper._();
|
||||
|
||||
@override
|
||||
Conversation parse(Map<String, dynamic> m) => Conversation.fromJson(m);
|
||||
|
||||
@override
|
||||
String get type => "conversations";
|
||||
|
||||
Future<ConversationsList> getList() async =>
|
||||
ConversationsList()..addAll(await super.getList());
|
||||
|
||||
/// Get a conversation
|
||||
Future<Conversation> get(int id) => first((t) => t.id == id);
|
||||
}
|
Reference in New Issue
Block a user