Restructuration majeure du projet: migration de flutt vers app, ajout de l'API et mise à jour du site web
This commit is contained in:
104
app/lib/chat/models/anonymous_user_model.dart
Normal file
104
app/lib/chat/models/anonymous_user_model.dart
Normal file
@@ -0,0 +1,104 @@
|
||||
import 'package:hive/hive.dart';
|
||||
import 'package:equatable/equatable.dart';
|
||||
|
||||
part 'anonymous_user_model.g.dart';
|
||||
|
||||
/// Modèle d'utilisateur anonyme pour le système de chat
|
||||
///
|
||||
/// Ce modèle représente un utilisateur anonyme (pour le cas Resalice)
|
||||
/// et permet de tracker sa conversion éventuelle en utilisateur authentifié
|
||||
|
||||
@HiveType(typeId: 24)
|
||||
class AnonymousUserModel extends HiveObject with EquatableMixin {
|
||||
@HiveField(0)
|
||||
final String id;
|
||||
|
||||
@HiveField(1)
|
||||
final String deviceId;
|
||||
|
||||
@HiveField(2)
|
||||
final String? name;
|
||||
|
||||
@HiveField(3)
|
||||
final String? email;
|
||||
|
||||
@HiveField(4)
|
||||
final DateTime createdAt;
|
||||
|
||||
@HiveField(5)
|
||||
final String? convertedToUserId;
|
||||
|
||||
@HiveField(6)
|
||||
final Map<String, dynamic>? metadata;
|
||||
|
||||
AnonymousUserModel({
|
||||
required this.id,
|
||||
required this.deviceId,
|
||||
this.name,
|
||||
this.email,
|
||||
required this.createdAt,
|
||||
this.convertedToUserId,
|
||||
this.metadata,
|
||||
});
|
||||
|
||||
/// Crée une instance depuis le JSON
|
||||
factory AnonymousUserModel.fromJson(Map<String, dynamic> json) {
|
||||
return AnonymousUserModel(
|
||||
id: json['id'] as String,
|
||||
deviceId: json['device_id'] as String,
|
||||
name: json['name'] as String?,
|
||||
email: json['email'] as String?,
|
||||
createdAt: DateTime.parse(json['created_at'] as String),
|
||||
convertedToUserId: json['converted_to_user_id'] as String?,
|
||||
metadata: json['metadata'] as Map<String, dynamic>?,
|
||||
);
|
||||
}
|
||||
|
||||
/// Convertit l'instance en JSON
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
'id': id,
|
||||
'device_id': deviceId,
|
||||
'name': name,
|
||||
'email': email,
|
||||
'created_at': createdAt.toIso8601String(),
|
||||
'converted_to_user_id': convertedToUserId,
|
||||
'metadata': metadata,
|
||||
};
|
||||
}
|
||||
|
||||
/// Crée une copie modifiée de l'instance
|
||||
AnonymousUserModel copyWith({
|
||||
String? id,
|
||||
String? deviceId,
|
||||
String? name,
|
||||
String? email,
|
||||
DateTime? createdAt,
|
||||
String? convertedToUserId,
|
||||
Map<String, dynamic>? metadata,
|
||||
}) {
|
||||
return AnonymousUserModel(
|
||||
id: id ?? this.id,
|
||||
deviceId: deviceId ?? this.deviceId,
|
||||
name: name ?? this.name,
|
||||
email: email ?? this.email,
|
||||
createdAt: createdAt ?? this.createdAt,
|
||||
convertedToUserId: convertedToUserId ?? this.convertedToUserId,
|
||||
metadata: metadata ?? this.metadata,
|
||||
);
|
||||
}
|
||||
|
||||
/// Vérifie si l'utilisateur a été converti en utilisateur authentifié
|
||||
bool get isConverted => convertedToUserId != null;
|
||||
|
||||
@override
|
||||
List<Object?> get props => [
|
||||
id,
|
||||
deviceId,
|
||||
name,
|
||||
email,
|
||||
createdAt,
|
||||
convertedToUserId,
|
||||
metadata,
|
||||
];
|
||||
}
|
||||
59
app/lib/chat/models/anonymous_user_model.g.dart
Normal file
59
app/lib/chat/models/anonymous_user_model.g.dart
Normal file
@@ -0,0 +1,59 @@
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of 'anonymous_user_model.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// TypeAdapterGenerator
|
||||
// **************************************************************************
|
||||
|
||||
class AnonymousUserModelAdapter extends TypeAdapter<AnonymousUserModel> {
|
||||
@override
|
||||
final int typeId = 24;
|
||||
|
||||
@override
|
||||
AnonymousUserModel read(BinaryReader reader) {
|
||||
final numOfFields = reader.readByte();
|
||||
final fields = <int, dynamic>{
|
||||
for (int i = 0; i < numOfFields; i++) reader.readByte(): reader.read(),
|
||||
};
|
||||
return AnonymousUserModel(
|
||||
id: fields[0] as String,
|
||||
deviceId: fields[1] as String,
|
||||
name: fields[2] as String?,
|
||||
email: fields[3] as String?,
|
||||
createdAt: fields[4] as DateTime,
|
||||
convertedToUserId: fields[5] as String?,
|
||||
metadata: (fields[6] as Map?)?.cast<String, dynamic>(),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
void write(BinaryWriter writer, AnonymousUserModel obj) {
|
||||
writer
|
||||
..writeByte(7)
|
||||
..writeByte(0)
|
||||
..write(obj.id)
|
||||
..writeByte(1)
|
||||
..write(obj.deviceId)
|
||||
..writeByte(2)
|
||||
..write(obj.name)
|
||||
..writeByte(3)
|
||||
..write(obj.email)
|
||||
..writeByte(4)
|
||||
..write(obj.createdAt)
|
||||
..writeByte(5)
|
||||
..write(obj.convertedToUserId)
|
||||
..writeByte(6)
|
||||
..write(obj.metadata);
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => typeId.hashCode;
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) =>
|
||||
identical(this, other) ||
|
||||
other is AnonymousUserModelAdapter &&
|
||||
runtimeType == other.runtimeType &&
|
||||
typeId == other.typeId;
|
||||
}
|
||||
138
app/lib/chat/models/audience_target_model.dart
Normal file
138
app/lib/chat/models/audience_target_model.dart
Normal file
@@ -0,0 +1,138 @@
|
||||
import 'package:hive/hive.dart';
|
||||
import 'package:equatable/equatable.dart';
|
||||
|
||||
part 'audience_target_model.g.dart';
|
||||
|
||||
/// Modèle de cible d'audience pour le système de chat
|
||||
///
|
||||
/// Ce modèle représente une cible d'audience pour les annonces et broadcasts
|
||||
/// Il supporte maintenant le ciblage combiné avec les filtres de rôle et d'entité
|
||||
|
||||
@HiveType(typeId: 23)
|
||||
class AudienceTargetModel extends HiveObject with EquatableMixin {
|
||||
@HiveField(0)
|
||||
final String id;
|
||||
|
||||
@HiveField(1)
|
||||
final String conversationId;
|
||||
|
||||
@HiveField(2)
|
||||
final String targetType;
|
||||
|
||||
@HiveField(3)
|
||||
final String? targetId;
|
||||
|
||||
@HiveField(4)
|
||||
final DateTime createdAt;
|
||||
|
||||
@HiveField(5)
|
||||
final String? roleFilter;
|
||||
|
||||
@HiveField(6)
|
||||
final String? entityFilter;
|
||||
|
||||
AudienceTargetModel({
|
||||
required this.id,
|
||||
required this.conversationId,
|
||||
required this.targetType,
|
||||
this.targetId,
|
||||
required this.createdAt,
|
||||
this.roleFilter,
|
||||
this.entityFilter,
|
||||
});
|
||||
|
||||
/// Crée une instance depuis le JSON
|
||||
factory AudienceTargetModel.fromJson(Map<String, dynamic> json) {
|
||||
return AudienceTargetModel(
|
||||
id: json['id'] as String,
|
||||
conversationId: json['conversation_id'] as String,
|
||||
targetType: json['target_type'] as String,
|
||||
targetId: json['target_id'] as String?,
|
||||
createdAt: DateTime.parse(json['created_at'] as String),
|
||||
roleFilter: json['role_filter'] as String?,
|
||||
entityFilter: json['entity_filter'] as String?,
|
||||
);
|
||||
}
|
||||
|
||||
/// Convertit l'instance en JSON
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
'id': id,
|
||||
'conversation_id': conversationId,
|
||||
'target_type': targetType,
|
||||
'target_id': targetId,
|
||||
'created_at': createdAt.toIso8601String(),
|
||||
'role_filter': roleFilter,
|
||||
'entity_filter': entityFilter,
|
||||
};
|
||||
}
|
||||
|
||||
/// Crée une copie modifiée de l'instance
|
||||
AudienceTargetModel copyWith({
|
||||
String? id,
|
||||
String? conversationId,
|
||||
String? targetType,
|
||||
String? targetId,
|
||||
DateTime? createdAt,
|
||||
String? roleFilter,
|
||||
String? entityFilter,
|
||||
}) {
|
||||
return AudienceTargetModel(
|
||||
id: id ?? this.id,
|
||||
conversationId: conversationId ?? this.conversationId,
|
||||
targetType: targetType ?? this.targetType,
|
||||
targetId: targetId ?? this.targetId,
|
||||
createdAt: createdAt ?? this.createdAt,
|
||||
roleFilter: roleFilter ?? this.roleFilter,
|
||||
entityFilter: entityFilter ?? this.entityFilter,
|
||||
);
|
||||
}
|
||||
|
||||
/// Vérifie si l'utilisateur est ciblé par cette règle
|
||||
bool targetsUser({
|
||||
required String userId,
|
||||
required int userRole,
|
||||
required String userEntityId,
|
||||
}) {
|
||||
switch (targetType) {
|
||||
case 'all':
|
||||
return true;
|
||||
case 'role':
|
||||
if (roleFilter != null && roleFilter != 'all') {
|
||||
return userRole.toString() == roleFilter;
|
||||
}
|
||||
return true;
|
||||
case 'entity':
|
||||
if (entityFilter != null && entityFilter != 'all') {
|
||||
return userEntityId == entityFilter;
|
||||
}
|
||||
return true;
|
||||
case 'combined':
|
||||
bool matchesRole = true;
|
||||
bool matchesEntity = true;
|
||||
|
||||
if (roleFilter != null && roleFilter != 'all') {
|
||||
matchesRole = userRole.toString() == roleFilter;
|
||||
}
|
||||
|
||||
if (entityFilter != null && entityFilter != 'all') {
|
||||
matchesEntity = userEntityId == entityFilter;
|
||||
}
|
||||
|
||||
return matchesRole && matchesEntity;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
List<Object?> get props => [
|
||||
id,
|
||||
conversationId,
|
||||
targetType,
|
||||
targetId,
|
||||
createdAt,
|
||||
roleFilter,
|
||||
entityFilter,
|
||||
];
|
||||
}
|
||||
59
app/lib/chat/models/audience_target_model.g.dart
Normal file
59
app/lib/chat/models/audience_target_model.g.dart
Normal file
@@ -0,0 +1,59 @@
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of 'audience_target_model.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// TypeAdapterGenerator
|
||||
// **************************************************************************
|
||||
|
||||
class AudienceTargetModelAdapter extends TypeAdapter<AudienceTargetModel> {
|
||||
@override
|
||||
final int typeId = 23;
|
||||
|
||||
@override
|
||||
AudienceTargetModel read(BinaryReader reader) {
|
||||
final numOfFields = reader.readByte();
|
||||
final fields = <int, dynamic>{
|
||||
for (int i = 0; i < numOfFields; i++) reader.readByte(): reader.read(),
|
||||
};
|
||||
return AudienceTargetModel(
|
||||
id: fields[0] as String,
|
||||
conversationId: fields[1] as String,
|
||||
targetType: fields[2] as String,
|
||||
targetId: fields[3] as String?,
|
||||
createdAt: fields[4] as DateTime,
|
||||
roleFilter: fields[5] as String?,
|
||||
entityFilter: fields[6] as String?,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
void write(BinaryWriter writer, AudienceTargetModel obj) {
|
||||
writer
|
||||
..writeByte(7)
|
||||
..writeByte(0)
|
||||
..write(obj.id)
|
||||
..writeByte(1)
|
||||
..write(obj.conversationId)
|
||||
..writeByte(2)
|
||||
..write(obj.targetType)
|
||||
..writeByte(3)
|
||||
..write(obj.targetId)
|
||||
..writeByte(4)
|
||||
..write(obj.createdAt)
|
||||
..writeByte(5)
|
||||
..write(obj.roleFilter)
|
||||
..writeByte(6)
|
||||
..write(obj.entityFilter);
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => typeId.hashCode;
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) =>
|
||||
identical(this, other) ||
|
||||
other is AudienceTargetModelAdapter &&
|
||||
runtimeType == other.runtimeType &&
|
||||
typeId == other.typeId;
|
||||
}
|
||||
15
app/lib/chat/models/chat_adapters.dart
Normal file
15
app/lib/chat/models/chat_adapters.dart
Normal file
@@ -0,0 +1,15 @@
|
||||
// Fichier central pour regrouper tous les adaptateurs Hive du module chat
|
||||
|
||||
// Exports des modèles et leurs adaptateurs
|
||||
export 'conversation_model.dart';
|
||||
export 'message_model.dart';
|
||||
export 'participant_model.dart';
|
||||
export 'anonymous_user_model.dart';
|
||||
export 'audience_target_model.dart';
|
||||
export 'notification_settings.dart';
|
||||
|
||||
// Fonction pour enregistrer tous les adaptateurs Hive du chat
|
||||
Future<void> registerChatHiveAdapters() async {
|
||||
// Les adaptateurs sont déjà générés dans les fichiers .g.dart
|
||||
// Ils sont automatiquement enregistrés lors de l'appel de registerAdapter
|
||||
}
|
||||
104
app/lib/chat/models/chat_config.dart
Normal file
104
app/lib/chat/models/chat_config.dart
Normal file
@@ -0,0 +1,104 @@
|
||||
import 'package:equatable/equatable.dart';
|
||||
|
||||
/// Configuration du module chat
|
||||
///
|
||||
/// Permet d'adapter le comportement du chat selon l'application
|
||||
/// (Geosector ou Resalice)
|
||||
|
||||
class ChatConfig with EquatableMixin {
|
||||
/// Active/désactive les annonces
|
||||
final bool enableAnnouncements;
|
||||
|
||||
/// Active/désactive la sélection de cibles pour les annonces
|
||||
final bool enableTargetSelection;
|
||||
|
||||
/// Active/désactive les statistiques des annonces
|
||||
final bool showAnnouncementStats;
|
||||
|
||||
/// Permission de réponse par défaut
|
||||
final String defaultReplyPermission;
|
||||
|
||||
/// Active/désactive les conversations anonymes
|
||||
final bool enableAnonymousConversations;
|
||||
|
||||
/// Active/désactive les conversations de groupe
|
||||
final bool enableGroupConversations;
|
||||
|
||||
/// Types de conversation autorisés
|
||||
final List<String> allowedConversationTypes;
|
||||
|
||||
/// Taille maximale des fichiers en Mo
|
||||
final int maxAttachmentSizeMB;
|
||||
|
||||
/// Nombre de messages par page
|
||||
final int messagePageSize;
|
||||
|
||||
ChatConfig({
|
||||
this.enableAnnouncements = true,
|
||||
this.enableTargetSelection = true,
|
||||
this.showAnnouncementStats = true,
|
||||
this.defaultReplyPermission = 'none',
|
||||
this.enableAnonymousConversations = false,
|
||||
this.enableGroupConversations = true,
|
||||
this.allowedConversationTypes = const [
|
||||
'one_to_one',
|
||||
'group',
|
||||
'announcement',
|
||||
'broadcast'
|
||||
],
|
||||
this.maxAttachmentSizeMB = 10,
|
||||
this.messagePageSize = 50,
|
||||
});
|
||||
|
||||
/// Configuration par défaut pour Geosector
|
||||
factory ChatConfig.geosector() {
|
||||
return ChatConfig(
|
||||
enableAnnouncements: true,
|
||||
enableTargetSelection: true,
|
||||
showAnnouncementStats: true,
|
||||
defaultReplyPermission: 'none',
|
||||
enableAnonymousConversations: false,
|
||||
enableGroupConversations: true,
|
||||
allowedConversationTypes: const [
|
||||
'one_to_one',
|
||||
'group',
|
||||
'announcement',
|
||||
'broadcast'
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
/// Configuration par défaut pour Resalice
|
||||
factory ChatConfig.resalice() {
|
||||
return ChatConfig(
|
||||
enableAnnouncements: false,
|
||||
enableTargetSelection: false,
|
||||
showAnnouncementStats: false,
|
||||
defaultReplyPermission: 'all',
|
||||
enableAnonymousConversations: true,
|
||||
enableGroupConversations: false,
|
||||
allowedConversationTypes: const [
|
||||
'one_to_one',
|
||||
'anonymous'
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
/// Vérifie si un type de conversation est autorisé
|
||||
bool isConversationTypeAllowed(String type) {
|
||||
return allowedConversationTypes.contains(type);
|
||||
}
|
||||
|
||||
@override
|
||||
List<Object?> get props => [
|
||||
enableAnnouncements,
|
||||
enableTargetSelection,
|
||||
showAnnouncementStats,
|
||||
defaultReplyPermission,
|
||||
enableAnonymousConversations,
|
||||
enableGroupConversations,
|
||||
allowedConversationTypes,
|
||||
maxAttachmentSizeMB,
|
||||
messagePageSize,
|
||||
];
|
||||
}
|
||||
139
app/lib/chat/models/conversation_model.dart
Normal file
139
app/lib/chat/models/conversation_model.dart
Normal file
@@ -0,0 +1,139 @@
|
||||
import 'package:hive/hive.dart';
|
||||
import 'package:equatable/equatable.dart';
|
||||
import 'participant_model.dart';
|
||||
|
||||
part 'conversation_model.g.dart';
|
||||
|
||||
/// Modèle de conversation pour le système de chat
|
||||
///
|
||||
/// Ce modèle représente une conversation entre utilisateurs
|
||||
/// Il supporte différents types de conversations :
|
||||
/// - one_to_one : conversation privée entre 2 utilisateurs
|
||||
/// - group : groupe de plusieurs utilisateurs
|
||||
/// - anonymous : conversation avec un utilisateur anonyme
|
||||
/// - broadcast : message diffusé à plusieurs utilisateurs
|
||||
/// - announcement : annonce officielle
|
||||
|
||||
@HiveType(typeId: 20)
|
||||
class ConversationModel extends HiveObject with EquatableMixin {
|
||||
@HiveField(0)
|
||||
final String id;
|
||||
|
||||
@HiveField(1)
|
||||
final String type;
|
||||
|
||||
@HiveField(2)
|
||||
final String? title;
|
||||
|
||||
@HiveField(3)
|
||||
final DateTime createdAt;
|
||||
|
||||
@HiveField(4)
|
||||
final DateTime updatedAt;
|
||||
|
||||
@HiveField(5)
|
||||
final List<ParticipantModel> participants;
|
||||
|
||||
@HiveField(6)
|
||||
final bool isSynced;
|
||||
|
||||
@HiveField(7)
|
||||
final String replyPermission;
|
||||
|
||||
@HiveField(8)
|
||||
final bool isPinned;
|
||||
|
||||
@HiveField(9)
|
||||
final DateTime? expiryDate;
|
||||
|
||||
ConversationModel({
|
||||
required this.id,
|
||||
required this.type,
|
||||
this.title,
|
||||
required this.createdAt,
|
||||
required this.updatedAt,
|
||||
required this.participants,
|
||||
this.isSynced = false,
|
||||
this.replyPermission = 'all',
|
||||
this.isPinned = false,
|
||||
this.expiryDate,
|
||||
});
|
||||
|
||||
/// Crée une instance depuis le JSON
|
||||
factory ConversationModel.fromJson(Map<String, dynamic> json) {
|
||||
return ConversationModel(
|
||||
id: json['id'] as String,
|
||||
type: json['type'] as String,
|
||||
title: json['title'] as String?,
|
||||
createdAt: DateTime.parse(json['created_at'] as String),
|
||||
updatedAt: DateTime.parse(json['updated_at'] as String),
|
||||
participants: (json['participants'] as List?)
|
||||
?.map((e) => ParticipantModel.fromJson(e as Map<String, dynamic>))
|
||||
.toList() ??
|
||||
[],
|
||||
isSynced: json['is_synced'] as bool? ?? false,
|
||||
replyPermission: json['reply_permission'] as String? ?? 'all',
|
||||
isPinned: json['is_pinned'] as bool? ?? false,
|
||||
expiryDate: json['expiry_date'] != null
|
||||
? DateTime.parse(json['expiry_date'] as String)
|
||||
: null,
|
||||
);
|
||||
}
|
||||
|
||||
/// Convertit l'instance en JSON
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
'id': id,
|
||||
'type': type,
|
||||
'title': title,
|
||||
'created_at': createdAt.toIso8601String(),
|
||||
'updated_at': updatedAt.toIso8601String(),
|
||||
'participants': participants.map((e) => e.toJson()).toList(),
|
||||
'is_synced': isSynced,
|
||||
'reply_permission': replyPermission,
|
||||
'is_pinned': isPinned,
|
||||
'expiry_date': expiryDate?.toIso8601String(),
|
||||
};
|
||||
}
|
||||
|
||||
/// Crée une copie modifiée de l'instance
|
||||
ConversationModel copyWith({
|
||||
String? id,
|
||||
String? type,
|
||||
String? title,
|
||||
DateTime? createdAt,
|
||||
DateTime? updatedAt,
|
||||
List<ParticipantModel>? participants,
|
||||
bool? isSynced,
|
||||
String? replyPermission,
|
||||
bool? isPinned,
|
||||
DateTime? expiryDate,
|
||||
}) {
|
||||
return ConversationModel(
|
||||
id: id ?? this.id,
|
||||
type: type ?? this.type,
|
||||
title: title ?? this.title,
|
||||
createdAt: createdAt ?? this.createdAt,
|
||||
updatedAt: updatedAt ?? this.updatedAt,
|
||||
participants: participants ?? this.participants,
|
||||
isSynced: isSynced ?? this.isSynced,
|
||||
replyPermission: replyPermission ?? this.replyPermission,
|
||||
isPinned: isPinned ?? this.isPinned,
|
||||
expiryDate: expiryDate ?? this.expiryDate,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
List<Object?> get props => [
|
||||
id,
|
||||
type,
|
||||
title,
|
||||
createdAt,
|
||||
updatedAt,
|
||||
participants,
|
||||
isSynced,
|
||||
replyPermission,
|
||||
isPinned,
|
||||
expiryDate,
|
||||
];
|
||||
}
|
||||
68
app/lib/chat/models/conversation_model.g.dart
Normal file
68
app/lib/chat/models/conversation_model.g.dart
Normal file
@@ -0,0 +1,68 @@
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of 'conversation_model.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// TypeAdapterGenerator
|
||||
// **************************************************************************
|
||||
|
||||
class ConversationModelAdapter extends TypeAdapter<ConversationModel> {
|
||||
@override
|
||||
final int typeId = 20;
|
||||
|
||||
@override
|
||||
ConversationModel read(BinaryReader reader) {
|
||||
final numOfFields = reader.readByte();
|
||||
final fields = <int, dynamic>{
|
||||
for (int i = 0; i < numOfFields; i++) reader.readByte(): reader.read(),
|
||||
};
|
||||
return ConversationModel(
|
||||
id: fields[0] as String,
|
||||
type: fields[1] as String,
|
||||
title: fields[2] as String?,
|
||||
createdAt: fields[3] as DateTime,
|
||||
updatedAt: fields[4] as DateTime,
|
||||
participants: (fields[5] as List).cast<ParticipantModel>(),
|
||||
isSynced: fields[6] as bool,
|
||||
replyPermission: fields[7] as String,
|
||||
isPinned: fields[8] as bool,
|
||||
expiryDate: fields[9] as DateTime?,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
void write(BinaryWriter writer, ConversationModel obj) {
|
||||
writer
|
||||
..writeByte(10)
|
||||
..writeByte(0)
|
||||
..write(obj.id)
|
||||
..writeByte(1)
|
||||
..write(obj.type)
|
||||
..writeByte(2)
|
||||
..write(obj.title)
|
||||
..writeByte(3)
|
||||
..write(obj.createdAt)
|
||||
..writeByte(4)
|
||||
..write(obj.updatedAt)
|
||||
..writeByte(5)
|
||||
..write(obj.participants)
|
||||
..writeByte(6)
|
||||
..write(obj.isSynced)
|
||||
..writeByte(7)
|
||||
..write(obj.replyPermission)
|
||||
..writeByte(8)
|
||||
..write(obj.isPinned)
|
||||
..writeByte(9)
|
||||
..write(obj.expiryDate);
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => typeId.hashCode;
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) =>
|
||||
identical(this, other) ||
|
||||
other is ConversationModelAdapter &&
|
||||
runtimeType == other.runtimeType &&
|
||||
typeId == other.typeId;
|
||||
}
|
||||
140
app/lib/chat/models/message_model.dart
Normal file
140
app/lib/chat/models/message_model.dart
Normal file
@@ -0,0 +1,140 @@
|
||||
import 'package:hive/hive.dart';
|
||||
import 'package:equatable/equatable.dart';
|
||||
|
||||
part 'message_model.g.dart';
|
||||
|
||||
/// Modèle de message pour le système de chat
|
||||
///
|
||||
/// Ce modèle représente un message échangé dans une conversation
|
||||
|
||||
@HiveType(typeId: 21)
|
||||
class MessageModel extends HiveObject with EquatableMixin {
|
||||
@HiveField(0)
|
||||
final String id;
|
||||
|
||||
@HiveField(1)
|
||||
final String conversationId;
|
||||
|
||||
@HiveField(2)
|
||||
final String? senderId;
|
||||
|
||||
@HiveField(3)
|
||||
final String senderType;
|
||||
|
||||
@HiveField(4)
|
||||
final String content;
|
||||
|
||||
@HiveField(5)
|
||||
final String contentType;
|
||||
|
||||
@HiveField(6)
|
||||
final DateTime createdAt;
|
||||
|
||||
@HiveField(7)
|
||||
final DateTime? deliveredAt;
|
||||
|
||||
@HiveField(8)
|
||||
final DateTime? readAt;
|
||||
|
||||
@HiveField(9)
|
||||
final String status;
|
||||
|
||||
@HiveField(10)
|
||||
final bool isAnnouncement;
|
||||
|
||||
MessageModel({
|
||||
required this.id,
|
||||
required this.conversationId,
|
||||
this.senderId,
|
||||
required this.senderType,
|
||||
required this.content,
|
||||
required this.contentType,
|
||||
required this.createdAt,
|
||||
this.deliveredAt,
|
||||
this.readAt,
|
||||
required this.status,
|
||||
this.isAnnouncement = false,
|
||||
});
|
||||
|
||||
/// Crée une instance depuis le JSON
|
||||
factory MessageModel.fromJson(Map<String, dynamic> json) {
|
||||
return MessageModel(
|
||||
id: json['id'] as String,
|
||||
conversationId: json['conversation_id'] as String,
|
||||
senderId: json['sender_id'] as String?,
|
||||
senderType: json['sender_type'] as String,
|
||||
content: json['content'] as String,
|
||||
contentType: json['content_type'] as String,
|
||||
createdAt: DateTime.parse(json['created_at'] as String),
|
||||
deliveredAt: json['delivered_at'] != null
|
||||
? DateTime.parse(json['delivered_at'] as String)
|
||||
: null,
|
||||
readAt: json['read_at'] != null
|
||||
? DateTime.parse(json['read_at'] as String)
|
||||
: null,
|
||||
status: json['status'] as String,
|
||||
isAnnouncement: json['is_announcement'] as bool? ?? false,
|
||||
);
|
||||
}
|
||||
|
||||
/// Convertit l'instance en JSON
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
'id': id,
|
||||
'conversation_id': conversationId,
|
||||
'sender_id': senderId,
|
||||
'sender_type': senderType,
|
||||
'content': content,
|
||||
'content_type': contentType,
|
||||
'created_at': createdAt.toIso8601String(),
|
||||
'delivered_at': deliveredAt?.toIso8601String(),
|
||||
'read_at': readAt?.toIso8601String(),
|
||||
'status': status,
|
||||
'is_announcement': isAnnouncement,
|
||||
};
|
||||
}
|
||||
|
||||
/// Crée une copie modifiée de l'instance
|
||||
MessageModel copyWith({
|
||||
String? id,
|
||||
String? conversationId,
|
||||
String? senderId,
|
||||
String? senderType,
|
||||
String? content,
|
||||
String? contentType,
|
||||
DateTime? createdAt,
|
||||
DateTime? deliveredAt,
|
||||
DateTime? readAt,
|
||||
String? status,
|
||||
bool? isAnnouncement,
|
||||
}) {
|
||||
return MessageModel(
|
||||
id: id ?? this.id,
|
||||
conversationId: conversationId ?? this.conversationId,
|
||||
senderId: senderId ?? this.senderId,
|
||||
senderType: senderType ?? this.senderType,
|
||||
content: content ?? this.content,
|
||||
contentType: contentType ?? this.contentType,
|
||||
createdAt: createdAt ?? this.createdAt,
|
||||
deliveredAt: deliveredAt ?? this.deliveredAt,
|
||||
readAt: readAt ?? this.readAt,
|
||||
status: status ?? this.status,
|
||||
isAnnouncement: isAnnouncement ?? this.isAnnouncement,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
List<Object?> get props => [
|
||||
id,
|
||||
conversationId,
|
||||
senderId,
|
||||
senderType,
|
||||
content,
|
||||
contentType,
|
||||
createdAt,
|
||||
deliveredAt,
|
||||
readAt,
|
||||
status,
|
||||
isAnnouncement,
|
||||
];
|
||||
}
|
||||
71
app/lib/chat/models/message_model.g.dart
Normal file
71
app/lib/chat/models/message_model.g.dart
Normal file
@@ -0,0 +1,71 @@
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of 'message_model.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// TypeAdapterGenerator
|
||||
// **************************************************************************
|
||||
|
||||
class MessageModelAdapter extends TypeAdapter<MessageModel> {
|
||||
@override
|
||||
final int typeId = 21;
|
||||
|
||||
@override
|
||||
MessageModel read(BinaryReader reader) {
|
||||
final numOfFields = reader.readByte();
|
||||
final fields = <int, dynamic>{
|
||||
for (int i = 0; i < numOfFields; i++) reader.readByte(): reader.read(),
|
||||
};
|
||||
return MessageModel(
|
||||
id: fields[0] as String,
|
||||
conversationId: fields[1] as String,
|
||||
senderId: fields[2] as String?,
|
||||
senderType: fields[3] as String,
|
||||
content: fields[4] as String,
|
||||
contentType: fields[5] as String,
|
||||
createdAt: fields[6] as DateTime,
|
||||
deliveredAt: fields[7] as DateTime?,
|
||||
readAt: fields[8] as DateTime?,
|
||||
status: fields[9] as String,
|
||||
isAnnouncement: fields[10] as bool,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
void write(BinaryWriter writer, MessageModel obj) {
|
||||
writer
|
||||
..writeByte(11)
|
||||
..writeByte(0)
|
||||
..write(obj.id)
|
||||
..writeByte(1)
|
||||
..write(obj.conversationId)
|
||||
..writeByte(2)
|
||||
..write(obj.senderId)
|
||||
..writeByte(3)
|
||||
..write(obj.senderType)
|
||||
..writeByte(4)
|
||||
..write(obj.content)
|
||||
..writeByte(5)
|
||||
..write(obj.contentType)
|
||||
..writeByte(6)
|
||||
..write(obj.createdAt)
|
||||
..writeByte(7)
|
||||
..write(obj.deliveredAt)
|
||||
..writeByte(8)
|
||||
..write(obj.readAt)
|
||||
..writeByte(9)
|
||||
..write(obj.status)
|
||||
..writeByte(10)
|
||||
..write(obj.isAnnouncement);
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => typeId.hashCode;
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) =>
|
||||
identical(this, other) ||
|
||||
other is MessageModelAdapter &&
|
||||
runtimeType == other.runtimeType &&
|
||||
typeId == other.typeId;
|
||||
}
|
||||
160
app/lib/chat/models/notification_settings.dart
Normal file
160
app/lib/chat/models/notification_settings.dart
Normal file
@@ -0,0 +1,160 @@
|
||||
import 'package:hive/hive.dart';
|
||||
import 'package:equatable/equatable.dart';
|
||||
|
||||
part 'notification_settings.g.dart';
|
||||
|
||||
/// Paramètres de notification pour le chat
|
||||
///
|
||||
/// Permet à l'utilisateur de configurer ses préférences de notification
|
||||
|
||||
@HiveType(typeId: 25)
|
||||
class NotificationSettings extends HiveObject with EquatableMixin {
|
||||
@HiveField(0)
|
||||
final bool enableNotifications;
|
||||
|
||||
@HiveField(1)
|
||||
final bool soundEnabled;
|
||||
|
||||
@HiveField(2)
|
||||
final bool vibrationEnabled;
|
||||
|
||||
@HiveField(3)
|
||||
final List<String> mutedConversations;
|
||||
|
||||
@HiveField(4)
|
||||
final bool showPreview;
|
||||
|
||||
@HiveField(5)
|
||||
final Map<String, bool> conversationNotifications;
|
||||
|
||||
@HiveField(6)
|
||||
final bool doNotDisturb;
|
||||
|
||||
@HiveField(7)
|
||||
final DateTime? doNotDisturbStart;
|
||||
|
||||
@HiveField(8)
|
||||
final DateTime? doNotDisturbEnd;
|
||||
|
||||
@HiveField(9)
|
||||
final String? deviceToken;
|
||||
|
||||
NotificationSettings({
|
||||
this.enableNotifications = true,
|
||||
this.soundEnabled = true,
|
||||
this.vibrationEnabled = true,
|
||||
this.mutedConversations = const [],
|
||||
this.showPreview = true,
|
||||
this.conversationNotifications = const {},
|
||||
this.doNotDisturb = false,
|
||||
this.doNotDisturbStart,
|
||||
this.doNotDisturbEnd,
|
||||
this.deviceToken,
|
||||
});
|
||||
|
||||
/// Crée une instance depuis le JSON
|
||||
factory NotificationSettings.fromJson(Map<String, dynamic> json) {
|
||||
return NotificationSettings(
|
||||
enableNotifications: json['enable_notifications'] as bool? ?? true,
|
||||
soundEnabled: json['sound_enabled'] as bool? ?? true,
|
||||
vibrationEnabled: json['vibration_enabled'] as bool? ?? true,
|
||||
mutedConversations: List<String>.from(json['muted_conversations'] ?? []),
|
||||
showPreview: json['show_preview'] as bool? ?? true,
|
||||
conversationNotifications: Map<String, bool>.from(json['conversation_notifications'] ?? {}),
|
||||
doNotDisturb: json['do_not_disturb'] as bool? ?? false,
|
||||
doNotDisturbStart: json['do_not_disturb_start'] != null
|
||||
? DateTime.parse(json['do_not_disturb_start'])
|
||||
: null,
|
||||
doNotDisturbEnd: json['do_not_disturb_end'] != null
|
||||
? DateTime.parse(json['do_not_disturb_end'])
|
||||
: null,
|
||||
deviceToken: json['device_token'] as String?,
|
||||
);
|
||||
}
|
||||
|
||||
/// Convertit l'instance en JSON
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
'enable_notifications': enableNotifications,
|
||||
'sound_enabled': soundEnabled,
|
||||
'vibration_enabled': vibrationEnabled,
|
||||
'muted_conversations': mutedConversations,
|
||||
'show_preview': showPreview,
|
||||
'conversation_notifications': conversationNotifications,
|
||||
'do_not_disturb': doNotDisturb,
|
||||
'do_not_disturb_start': doNotDisturbStart?.toIso8601String(),
|
||||
'do_not_disturb_end': doNotDisturbEnd?.toIso8601String(),
|
||||
'device_token': deviceToken,
|
||||
};
|
||||
}
|
||||
|
||||
/// Crée une copie modifiée de l'instance
|
||||
NotificationSettings copyWith({
|
||||
bool? enableNotifications,
|
||||
bool? soundEnabled,
|
||||
bool? vibrationEnabled,
|
||||
List<String>? mutedConversations,
|
||||
bool? showPreview,
|
||||
Map<String, bool>? conversationNotifications,
|
||||
bool? doNotDisturb,
|
||||
DateTime? doNotDisturbStart,
|
||||
DateTime? doNotDisturbEnd,
|
||||
String? deviceToken,
|
||||
}) {
|
||||
return NotificationSettings(
|
||||
enableNotifications: enableNotifications ?? this.enableNotifications,
|
||||
soundEnabled: soundEnabled ?? this.soundEnabled,
|
||||
vibrationEnabled: vibrationEnabled ?? this.vibrationEnabled,
|
||||
mutedConversations: mutedConversations ?? this.mutedConversations,
|
||||
showPreview: showPreview ?? this.showPreview,
|
||||
conversationNotifications: conversationNotifications ?? this.conversationNotifications,
|
||||
doNotDisturb: doNotDisturb ?? this.doNotDisturb,
|
||||
doNotDisturbStart: doNotDisturbStart ?? this.doNotDisturbStart,
|
||||
doNotDisturbEnd: doNotDisturbEnd ?? this.doNotDisturbEnd,
|
||||
deviceToken: deviceToken ?? this.deviceToken,
|
||||
);
|
||||
}
|
||||
|
||||
/// Vérifie si une conversation est en mode silencieux
|
||||
bool isConversationMuted(String conversationId) {
|
||||
return mutedConversations.contains(conversationId);
|
||||
}
|
||||
|
||||
/// Vérifie si les notifications sont activées pour une conversation
|
||||
bool areNotificationsEnabled(String conversationId) {
|
||||
if (!enableNotifications) return false;
|
||||
if (isConversationMuted(conversationId)) return false;
|
||||
if (doNotDisturb && _isInDoNotDisturbPeriod()) return false;
|
||||
|
||||
return conversationNotifications[conversationId] ?? true;
|
||||
}
|
||||
|
||||
/// Vérifie si on est dans la période "Ne pas déranger"
|
||||
bool _isInDoNotDisturbPeriod() {
|
||||
if (!doNotDisturb) return false;
|
||||
if (doNotDisturbStart == null || doNotDisturbEnd == null) return false;
|
||||
|
||||
final now = DateTime.now();
|
||||
if (doNotDisturbStart!.isBefore(doNotDisturbEnd!)) {
|
||||
// Période normale (ex: 22h à 8h)
|
||||
return now.isAfter(doNotDisturbStart!) && now.isBefore(doNotDisturbEnd!);
|
||||
} else {
|
||||
// Période qui chevauche minuit (ex: 20h à 6h)
|
||||
return now.isAfter(doNotDisturbStart!) || now.isBefore(doNotDisturbEnd!);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
List<Object?> get props => [
|
||||
enableNotifications,
|
||||
soundEnabled,
|
||||
vibrationEnabled,
|
||||
mutedConversations,
|
||||
showPreview,
|
||||
conversationNotifications,
|
||||
doNotDisturb,
|
||||
doNotDisturbStart,
|
||||
doNotDisturbEnd,
|
||||
deviceToken,
|
||||
];
|
||||
}
|
||||
68
app/lib/chat/models/notification_settings.g.dart
Normal file
68
app/lib/chat/models/notification_settings.g.dart
Normal file
@@ -0,0 +1,68 @@
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of 'notification_settings.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// TypeAdapterGenerator
|
||||
// **************************************************************************
|
||||
|
||||
class NotificationSettingsAdapter extends TypeAdapter<NotificationSettings> {
|
||||
@override
|
||||
final int typeId = 25;
|
||||
|
||||
@override
|
||||
NotificationSettings read(BinaryReader reader) {
|
||||
final numOfFields = reader.readByte();
|
||||
final fields = <int, dynamic>{
|
||||
for (int i = 0; i < numOfFields; i++) reader.readByte(): reader.read(),
|
||||
};
|
||||
return NotificationSettings(
|
||||
enableNotifications: fields[0] as bool,
|
||||
soundEnabled: fields[1] as bool,
|
||||
vibrationEnabled: fields[2] as bool,
|
||||
mutedConversations: (fields[3] as List).cast<String>(),
|
||||
showPreview: fields[4] as bool,
|
||||
conversationNotifications: (fields[5] as Map).cast<String, bool>(),
|
||||
doNotDisturb: fields[6] as bool,
|
||||
doNotDisturbStart: fields[7] as DateTime?,
|
||||
doNotDisturbEnd: fields[8] as DateTime?,
|
||||
deviceToken: fields[9] as String?,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
void write(BinaryWriter writer, NotificationSettings obj) {
|
||||
writer
|
||||
..writeByte(10)
|
||||
..writeByte(0)
|
||||
..write(obj.enableNotifications)
|
||||
..writeByte(1)
|
||||
..write(obj.soundEnabled)
|
||||
..writeByte(2)
|
||||
..write(obj.vibrationEnabled)
|
||||
..writeByte(3)
|
||||
..write(obj.mutedConversations)
|
||||
..writeByte(4)
|
||||
..write(obj.showPreview)
|
||||
..writeByte(5)
|
||||
..write(obj.conversationNotifications)
|
||||
..writeByte(6)
|
||||
..write(obj.doNotDisturb)
|
||||
..writeByte(7)
|
||||
..write(obj.doNotDisturbStart)
|
||||
..writeByte(8)
|
||||
..write(obj.doNotDisturbEnd)
|
||||
..writeByte(9)
|
||||
..write(obj.deviceToken);
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => typeId.hashCode;
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) =>
|
||||
identical(this, other) ||
|
||||
other is NotificationSettingsAdapter &&
|
||||
runtimeType == other.runtimeType &&
|
||||
typeId == other.typeId;
|
||||
}
|
||||
118
app/lib/chat/models/participant_model.dart
Normal file
118
app/lib/chat/models/participant_model.dart
Normal file
@@ -0,0 +1,118 @@
|
||||
import 'package:hive/hive.dart';
|
||||
import 'package:equatable/equatable.dart';
|
||||
|
||||
part 'participant_model.g.dart';
|
||||
|
||||
/// Modèle de participant pour le système de chat
|
||||
///
|
||||
/// Ce modèle représente un participant à une conversation
|
||||
|
||||
@HiveType(typeId: 22)
|
||||
class ParticipantModel extends HiveObject with EquatableMixin {
|
||||
@HiveField(0)
|
||||
final String id;
|
||||
|
||||
@HiveField(1)
|
||||
final String conversationId;
|
||||
|
||||
@HiveField(2)
|
||||
final String? userId;
|
||||
|
||||
@HiveField(3)
|
||||
final String? anonymousId;
|
||||
|
||||
@HiveField(4)
|
||||
final String role;
|
||||
|
||||
@HiveField(5)
|
||||
final DateTime joinedAt;
|
||||
|
||||
@HiveField(6)
|
||||
final String? lastReadMessageId;
|
||||
|
||||
@HiveField(7)
|
||||
final bool viaTarget;
|
||||
|
||||
@HiveField(8)
|
||||
final bool? canReply;
|
||||
|
||||
ParticipantModel({
|
||||
required this.id,
|
||||
required this.conversationId,
|
||||
this.userId,
|
||||
this.anonymousId,
|
||||
required this.role,
|
||||
required this.joinedAt,
|
||||
this.lastReadMessageId,
|
||||
this.viaTarget = false,
|
||||
this.canReply,
|
||||
});
|
||||
|
||||
/// Crée une instance depuis le JSON
|
||||
factory ParticipantModel.fromJson(Map<String, dynamic> json) {
|
||||
return ParticipantModel(
|
||||
id: json['id'] as String,
|
||||
conversationId: json['conversation_id'] as String,
|
||||
userId: json['user_id'] as String?,
|
||||
anonymousId: json['anonymous_id'] as String?,
|
||||
role: json['role'] as String,
|
||||
joinedAt: DateTime.parse(json['joined_at'] as String),
|
||||
lastReadMessageId: json['last_read_message_id'] as String?,
|
||||
viaTarget: json['via_target'] as bool? ?? false,
|
||||
canReply: json['can_reply'] as bool?,
|
||||
);
|
||||
}
|
||||
|
||||
/// Convertit l'instance en JSON
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
'id': id,
|
||||
'conversation_id': conversationId,
|
||||
'user_id': userId,
|
||||
'anonymous_id': anonymousId,
|
||||
'role': role,
|
||||
'joined_at': joinedAt.toIso8601String(),
|
||||
'last_read_message_id': lastReadMessageId,
|
||||
'via_target': viaTarget,
|
||||
'can_reply': canReply,
|
||||
};
|
||||
}
|
||||
|
||||
/// Crée une copie modifiée de l'instance
|
||||
ParticipantModel copyWith({
|
||||
String? id,
|
||||
String? conversationId,
|
||||
String? userId,
|
||||
String? anonymousId,
|
||||
String? role,
|
||||
DateTime? joinedAt,
|
||||
String? lastReadMessageId,
|
||||
bool? viaTarget,
|
||||
bool? canReply,
|
||||
}) {
|
||||
return ParticipantModel(
|
||||
id: id ?? this.id,
|
||||
conversationId: conversationId ?? this.conversationId,
|
||||
userId: userId ?? this.userId,
|
||||
anonymousId: anonymousId ?? this.anonymousId,
|
||||
role: role ?? this.role,
|
||||
joinedAt: joinedAt ?? this.joinedAt,
|
||||
lastReadMessageId: lastReadMessageId ?? this.lastReadMessageId,
|
||||
viaTarget: viaTarget ?? this.viaTarget,
|
||||
canReply: canReply ?? this.canReply,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
List<Object?> get props => [
|
||||
id,
|
||||
conversationId,
|
||||
userId,
|
||||
anonymousId,
|
||||
role,
|
||||
joinedAt,
|
||||
lastReadMessageId,
|
||||
viaTarget,
|
||||
canReply,
|
||||
];
|
||||
}
|
||||
65
app/lib/chat/models/participant_model.g.dart
Normal file
65
app/lib/chat/models/participant_model.g.dart
Normal file
@@ -0,0 +1,65 @@
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of 'participant_model.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// TypeAdapterGenerator
|
||||
// **************************************************************************
|
||||
|
||||
class ParticipantModelAdapter extends TypeAdapter<ParticipantModel> {
|
||||
@override
|
||||
final int typeId = 22;
|
||||
|
||||
@override
|
||||
ParticipantModel read(BinaryReader reader) {
|
||||
final numOfFields = reader.readByte();
|
||||
final fields = <int, dynamic>{
|
||||
for (int i = 0; i < numOfFields; i++) reader.readByte(): reader.read(),
|
||||
};
|
||||
return ParticipantModel(
|
||||
id: fields[0] as String,
|
||||
conversationId: fields[1] as String,
|
||||
userId: fields[2] as String?,
|
||||
anonymousId: fields[3] as String?,
|
||||
role: fields[4] as String,
|
||||
joinedAt: fields[5] as DateTime,
|
||||
lastReadMessageId: fields[6] as String?,
|
||||
viaTarget: fields[7] as bool,
|
||||
canReply: fields[8] as bool?,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
void write(BinaryWriter writer, ParticipantModel obj) {
|
||||
writer
|
||||
..writeByte(9)
|
||||
..writeByte(0)
|
||||
..write(obj.id)
|
||||
..writeByte(1)
|
||||
..write(obj.conversationId)
|
||||
..writeByte(2)
|
||||
..write(obj.userId)
|
||||
..writeByte(3)
|
||||
..write(obj.anonymousId)
|
||||
..writeByte(4)
|
||||
..write(obj.role)
|
||||
..writeByte(5)
|
||||
..write(obj.joinedAt)
|
||||
..writeByte(6)
|
||||
..write(obj.lastReadMessageId)
|
||||
..writeByte(7)
|
||||
..write(obj.viaTarget)
|
||||
..writeByte(8)
|
||||
..write(obj.canReply);
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => typeId.hashCode;
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) =>
|
||||
identical(this, other) ||
|
||||
other is ParticipantModelAdapter &&
|
||||
runtimeType == other.runtimeType &&
|
||||
typeId == other.typeId;
|
||||
}
|
||||
Reference in New Issue
Block a user