import 'package:comunic/helpers/serialization/base_serialization_helper.dart'; import 'package:comunic/lists/users_list.dart'; import 'package:comunic/models/displayed_content.dart'; import 'package:comunic/utils/account_utils.dart' as account; import 'package:comunic/utils/intl_utils.dart'; import 'package:flutter/material.dart'; /// Single conversation message /// /// @author Pierre HUBERT enum ConversationMessageFileType { IMAGE, VIDEO, AUDIO, PDF, ZIP, OTHER, } const _ConversationFileMimeTypeMapping = { "image/jpeg": ConversationMessageFileType.IMAGE, "image/png": ConversationMessageFileType.IMAGE, "image/gif": ConversationMessageFileType.IMAGE, "video/mp4": ConversationMessageFileType.VIDEO, "audio/m4a": ConversationMessageFileType.AUDIO, "audio/mpeg": ConversationMessageFileType.AUDIO, "application/pdf": ConversationMessageFileType.PDF, "application/zip": ConversationMessageFileType.ZIP, }; class ConversationMessageFile { final String? url; final int? size; final String? name; final String? thumbnail; final String? type; const ConversationMessageFile({ required String this.url, required int this.size, required String this.name, required this.thumbnail, required String this.type, }); /// Get the type of file ConversationMessageFileType? get fileType { if (type != null && _ConversationFileMimeTypeMapping.containsKey(type)) return _ConversationFileMimeTypeMapping[type!]; else return ConversationMessageFileType.OTHER; } /// Get the icon associated with file type IconData get icon { switch (fileType) { case ConversationMessageFileType.IMAGE: return Icons.image; case ConversationMessageFileType.VIDEO: return Icons.video_library; case ConversationMessageFileType.AUDIO: return Icons.audiotrack; case ConversationMessageFileType.PDF: return Icons.picture_as_pdf; case ConversationMessageFileType.ZIP: return Icons.archive; default: return Icons.insert_drive_file; } } bool get hasThumbnail => thumbnail != null; Map toJson() => { "url": url, "size": size, "name": name, "thumbnail": thumbnail, "type": type }; ConversationMessageFile.fromJson(Map json) : url = json["url"], size = json["size"], name = json["name"], thumbnail = json["thumbnail"], type = json["type"]; } enum ConversationServerMessageType { USER_CREATED_CONVERSATION, USER_ADDED_ANOTHER_USER, USER_LEFT_CONV, USER_REMOVED_ANOTHER_USER } class ConversationServerMessage { final ConversationServerMessageType type; final int? userID; final int? userWhoAdded; final int? userAdded; final int? userWhoRemoved; final int? userRemoved; const ConversationServerMessage({ required this.type, required this.userID, required this.userWhoAdded, required this.userAdded, required this.userWhoRemoved, required this.userRemoved, }) : assert(userID != null || (type != ConversationServerMessageType.USER_CREATED_CONVERSATION && type != ConversationServerMessageType.USER_LEFT_CONV)), assert((userWhoAdded != null && userAdded != null) || type != ConversationServerMessageType.USER_ADDED_ANOTHER_USER), assert((userWhoRemoved != null && userRemoved != null) || type != ConversationServerMessageType.USER_REMOVED_ANOTHER_USER); Set get usersID { switch (type) { case ConversationServerMessageType.USER_CREATED_CONVERSATION: case ConversationServerMessageType.USER_LEFT_CONV: return Set()..add(userID); case ConversationServerMessageType.USER_ADDED_ANOTHER_USER: return Set() ..add(userWhoAdded) ..add(userAdded); case ConversationServerMessageType.USER_REMOVED_ANOTHER_USER: return Set() ..add(userWhoRemoved) ..add(userRemoved); } } String? getText(UsersList? list) { switch (type) { case ConversationServerMessageType.USER_CREATED_CONVERSATION: return tr("%1% created the conversation", args: {"1": list!.getUser(userID).fullName}); case ConversationServerMessageType.USER_ADDED_ANOTHER_USER: return tr("%1% added %2% to the conversation", args: { "1": list!.getUser(userWhoAdded).fullName, "2": list.getUser(userAdded).fullName, }); case ConversationServerMessageType.USER_LEFT_CONV: return tr("%1% left the conversation", args: { "1": list!.getUser(userID).fullName, }); case ConversationServerMessageType.USER_REMOVED_ANOTHER_USER: return tr("%1% removed %2% from the conversation", args: { "1": list!.getUser(userWhoRemoved).fullName, "2": list.getUser(userRemoved).fullName, }); } } Map toJson() => { "type": type.toString(), "userID": userID, "userWhoAdded": userWhoAdded, "userAdded": userAdded, "userWhoRemoved": userWhoRemoved, "userRemoved": userRemoved, }; ConversationServerMessage.fromJson(Map json) : type = ConversationServerMessageType.values .firstWhere((el) => el.toString() == json["type"]), userID = json["userID"], userWhoAdded = json["userWhoAdded"], userAdded = json["userAdded"], userWhoRemoved = json["userWhoRemoved"], userRemoved = json["userRemoved"]; } class ConversationMessage extends SerializableElement { final int? id; final int? convID; final int? userID; final int? timeSent; final DisplayedString message; final ConversationMessageFile? file; final ConversationServerMessage? serverMessage; ConversationMessage({ required int this.id, required int this.convID, required this.userID, required int this.timeSent, required this.message, required this.file, required this.serverMessage, }) : assert(userID != null || serverMessage != null), assert(!message.isNull || file != null || serverMessage != null); DateTime get date => DateTime.fromMillisecondsSinceEpoch(timeSent! * 1000); bool get hasMessage => !message.isNull && message.length > 0; bool get hasFile => file != null; bool get isOwner => account.userID() == userID; bool get isServerMessage => serverMessage != null; /// Get the list of the ID of the users implied in this message Set get usersID { if (userID != null) return Set()..add(userID); if (serverMessage != null) return serverMessage!.usersID; return Set(); } @override int compareTo(ConversationMessage other) { return id!.compareTo(other.id!); } Map toJson() { return { "id": id, "convID": convID, "userID": userID, "timeSent": timeSent, "message": message.content, "file": file?.toJson(), "serverMessage": serverMessage?.toJson(), }; } ConversationMessage.fromJson(Map map) : id = map["id"], convID = map["convID"], userID = map["userID"], timeSent = map["timeSent"], message = DisplayedString(map["message"]), file = map["file"] == null ? null : ConversationMessageFile.fromJson(map["file"]), serverMessage = map["serverMessage"] == null ? null : ConversationServerMessage.fromJson(map["serverMessage"]); }