mirror of
				https://gitlab.com/comunic/comunicmobile
				synced 2025-11-03 19:54:12 +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