feat: Release version 3.1.4 - Mode terrain et génération PDF

 Nouvelles fonctionnalités:
- Ajout du mode terrain pour utilisation mobile hors connexion
- Génération automatique de reçus PDF avec template personnalisé
- Révision complète du système de cartes avec amélioration des performances

🔧 Améliorations techniques:
- Refactoring du module chat avec architecture simplifiée
- Optimisation du système de sécurité NIST SP 800-63B
- Amélioration de la gestion des secteurs géographiques
- Support UTF-8 étendu pour les noms d'utilisateurs

📱 Application mobile:
- Nouveau mode terrain dans user_field_mode_page
- Interface utilisateur adaptative pour conditions difficiles
- Synchronisation offline améliorée

🗺️ Cartographie:
- Optimisation des performances MapBox
- Meilleure gestion des tuiles hors ligne
- Amélioration de l'affichage des secteurs

📄 Documentation:
- Ajout guide Android (ANDROID-GUIDE.md)
- Documentation sécurité API (API-SECURITY.md)
- Guide module chat (CHAT_MODULE.md)

🐛 Corrections:
- Résolution des erreurs 400 lors de la création d'utilisateurs
- Correction de la validation des noms d'utilisateurs
- Fix des problèmes de synchronisation chat

🤖 Generated with Claude Code (https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2025-08-19 19:38:03 +02:00
parent 4f7247eb2d
commit 3443277d4a
185 changed files with 109354 additions and 102937 deletions

File diff suppressed because one or more lines are too long

View File

@@ -1,64 +0,0 @@
// **************************************************************************
// 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;
}

View File

@@ -2,45 +2,48 @@
// TypeAdapterGenerator
// **************************************************************************
class AudienceTargetModelAdapter extends TypeAdapter<AudienceTargetModel> {
class MessageAdapter extends TypeAdapter<Message> {
@override
final int typeId = 24;
final int typeId = 51;
@override
AudienceTargetModel read(BinaryReader reader) {
Message read(BinaryReader reader) {
final numOfFields = reader.readByte();
final fields = <int, dynamic>{
for (int i = 0; i < numOfFields; i++) reader.readByte(): reader.read(),
};
return AudienceTargetModel(
return Message(
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?,
roomId: fields[1] as String,
content: fields[2] as String,
senderId: fields[3] as int,
senderName: fields[4] as String,
sentAt: fields[5] as DateTime,
isMe: fields[6] as bool,
isRead: fields[7] as bool,
);
}
@override
void write(BinaryWriter writer, AudienceTargetModel obj) {
void write(BinaryWriter writer, Message obj) {
writer
..writeByte(7)
..writeByte(8)
..writeByte(0)
..write(obj.id)
..writeByte(1)
..write(obj.conversationId)
..write(obj.roomId)
..writeByte(2)
..write(obj.targetType)
..write(obj.content)
..writeByte(3)
..write(obj.targetId)
..write(obj.senderId)
..writeByte(4)
..write(obj.createdAt)
..write(obj.senderName)
..writeByte(5)
..write(obj.roleFilter)
..write(obj.sentAt)
..writeByte(6)
..write(obj.entityFilter);
..write(obj.isMe)
..writeByte(7)
..write(obj.isRead);
}
@override
@@ -49,7 +52,7 @@ class AudienceTargetModelAdapter extends TypeAdapter<AudienceTargetModel> {
@override
bool operator ==(Object other) =>
identical(this, other) ||
other is AudienceTargetModelAdapter &&
other is MessageAdapter &&
runtimeType == other.runtimeType &&
typeId == other.typeId;
}

View File

@@ -1,67 +0,0 @@
// **************************************************************************
// 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;
}

View File

@@ -1,64 +0,0 @@
// **************************************************************************
// 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;
}

View File

@@ -1,61 +0,0 @@
// **************************************************************************
// 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;
}

View File

@@ -2,45 +2,45 @@
// TypeAdapterGenerator
// **************************************************************************
class AnonymousUserModelAdapter extends TypeAdapter<AnonymousUserModel> {
class RoomAdapter extends TypeAdapter<Room> {
@override
final int typeId = 23;
final int typeId = 50;
@override
AnonymousUserModel read(BinaryReader reader) {
Room read(BinaryReader reader) {
final numOfFields = reader.readByte();
final fields = <int, dynamic>{
for (int i = 0; i < numOfFields; i++) reader.readByte(): reader.read(),
};
return AnonymousUserModel(
return Room(
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>(),
title: fields[1] as String,
type: fields[2] as String,
createdAt: fields[3] as DateTime,
lastMessage: fields[4] as String?,
lastMessageAt: fields[5] as DateTime?,
unreadCount: fields[6] as int,
);
}
@override
void write(BinaryWriter writer, AnonymousUserModel obj) {
void write(BinaryWriter writer, Room obj) {
writer
..writeByte(7)
..writeByte(0)
..write(obj.id)
..writeByte(1)
..write(obj.deviceId)
..write(obj.title)
..writeByte(2)
..write(obj.name)
..write(obj.type)
..writeByte(3)
..write(obj.email)
..writeByte(4)
..write(obj.createdAt)
..writeByte(4)
..write(obj.lastMessage)
..writeByte(5)
..write(obj.convertedToUserId)
..write(obj.lastMessageAt)
..writeByte(6)
..write(obj.metadata);
..write(obj.unreadCount);
}
@override
@@ -49,7 +49,7 @@ class AnonymousUserModelAdapter extends TypeAdapter<AnonymousUserModel> {
@override
bool operator ==(Object other) =>
identical(this, other) ||
other is AnonymousUserModelAdapter &&
other is RoomAdapter &&
runtimeType == other.runtimeType &&
typeId == other.typeId;
}