diff --git a/src/pages/chat/chat.ts b/src/pages/chat/chat.ts
index 82acb6b..a466ef6 100755
--- a/src/pages/chat/chat.ts
+++ b/src/pages/chat/chat.ts
@@ -382,7 +382,6 @@ class ChatElement extends HTMLElement {
throw new Error('No paired member found');
}
- // Formater la date pour n'avoir que l'heure et la date
const now = new Date();
const formattedTime = now.toLocaleString('fr-FR', {
day: '2-digit',
@@ -392,7 +391,6 @@ class ChatElement extends HTMLElement {
minute: '2-digit'
});
- // Créer le message au format attendu par messageStore
const newMessage = {
id: Date.now(),
sender: myAddresses[0],
@@ -401,9 +399,10 @@ class ChatElement extends HTMLElement {
type: 'text' as const
};
-
- messageStore.addMessage(this.selectedMemberId!, newMessage);
- this.messagesMock = messageStore.getMessages();
+ if (this.selectedMemberId) {
+ messageStore.addMessage(this.selectedMemberId!, newMessage);
+ this.messagesMock = messageStore.getMessages();
+ }
// Récupérer le process_id du parent (conversation)
const groupItem = this.shadowRoot?.querySelector('[data-process-id]');
@@ -541,15 +540,33 @@ class ChatElement extends HTMLElement {
const messageContent = document.createElement('div');
messageContent.className = 'message';
- if (message.sender === myAddresses[0]) {
- messageContent.classList.add('user');
+ if (message.type === 'file') {
messageContent.innerHTML = `
- ${message.text}
+ ${await addressToEmoji(message.sender)}:
+
+ 📎 ${message.fileName}
+
${message.time}
`;
+
+ // Ajouter le gestionnaire de clic pour le téléchargement
+ const fileSpan = messageContent.querySelector('.file-message');
+ fileSpan?.addEventListener('click', () => {
+ const fileKey = `file_${message.id}`;
+ const fileData = localStorage.getItem(fileKey);
+ if (fileData) {
+ // Créer un lien de téléchargement
+ const link = document.createElement('a');
+ link.href = fileData;
+ link.download = message.fileName;
+ document.body.appendChild(link);
+ link.click();
+ document.body.removeChild(link);
+ }
+ });
} else {
messageContent.innerHTML = `
- ${await addressToEmoji(memberAddress)}: ${message.text}
+ ${await addressToEmoji(message.sender)}: ${message.text}
${message.time}
`;
}
@@ -844,45 +861,187 @@ class ChatElement extends HTMLElement {
// Send a file
private async sendFile(file: File) {
- if (!this.selectedMemberId) return;
-
- const MAX_FILE_SIZE = 5 * 1024 * 1024;
+ // Ajouter une vérification de la taille avant la conversion en base64
+ const MAX_FILE_SIZE = 1 * 1024 * 1024; // Réduire à 1MB pour éviter les problèmes de quota
if (file.size > MAX_FILE_SIZE) {
- alert('File is too large. Maximum size is 5MB');
+ alert('Le fichier est trop volumineux. Taille maximum : 1MB');
return;
}
- const reader = new FileReader();
- reader.readAsDataURL(file);
-
- reader.onload = () => {
- const fileMessage = {
+ try {
+ const myAddresses = await this.getMemberFromDevice();
+ if (!myAddresses) {
+ throw new Error('No paired member found');
+ }
+
+ // Compresser l'image si c'est une image
+ let fileData: string;
+ if (file.type.startsWith('image/')) {
+ fileData = await this.compressImage(file);
+ } else {
+ fileData = await this.readFileAsBase64(file);
+ }
+
+ // Créer un message avec un texte descriptif au lieu du fileData
+ const newMessage = {
id: Date.now(),
- sender: "4NK",
+ sender: myAddresses[0],
+ text: `Fichier envoyé: ${file.name}`, // Ajouter un texte descriptif
fileName: file.name,
- fileData: reader.result,
- time: new Date().toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' }),
+ time: new Date().toLocaleString('fr-FR'),
type: 'file' as const
};
- messageStore.addMessage(this.selectedMemberId!, fileMessage);
- this.messagesMock = messageStore.getMessages();
- this.loadMemberChat(this.selectedMemberId!);
+ // Stocker le fileData séparément
+ try {
+ const fileKey = `file_${newMessage.id}`;
+ localStorage.setItem(fileKey, fileData);
+ } catch (storageError) {
+ console.error('Erreur de stockage du fichier:', storageError);
+ alert('Erreur lors du stockage du fichier. Essayez avec un fichier plus petit.');
+ return;
+ }
+
+ if (this.selectedMemberId) {
+ messageStore.addMessage(this.selectedMemberId, newMessage);
+ this.messagesMock = messageStore.getMessages();
+ }
+
+ // Récupérer le process_id du parent (conversation)
+ const groupItem = this.shadowRoot?.querySelector('[data-process-id]');
+ const parentProcessId = groupItem?.getAttribute('data-process-id');
+
+ if (!parentProcessId) {
+ throw new Error('Parent process ID not found');
+ }
+
+ const messageTemplate = {
+ process_id: parentProcessId,
+ parent_id: null,
+ description: 'file_message',
+ messages: {
+ state: 'initial',
+ object: {
+ type: 'file',
+ content: fileData,
+ metadata: {
+ created_at: newMessage.time,
+ last_updated: newMessage.time,
+ sender: myAddresses[0],
+ recipient: this.selectedMemberId,
+ fileName: file.name,
+ fileType: file.type
+ }
+ }
+ },
+ roles: {
+ public: {
+ members: [
+ { sp_addresses: myAddresses },
+ { sp_addresses: [this.selectedMemberId] }
+ ],
+ validation_rules: [
+ {
+ quorum: 0.0,
+ fields: ['description', 'messages'],
+ min_sig_member: 0.0,
+ },
+ ],
+ storages: [storageUrl]
+ },
+ owner: {
+ members: [
+ { sp_addresses: myAddresses },
+ { sp_addresses: [this.selectedMemberId] }
+ ],
+ validation_rules: [
+ {
+ quorum: 1.0,
+ fields: ['description', 'messages'],
+ min_sig_member: 1.0,
+ },
+ ],
+ storages: [storageUrl]
+ }
+ }
+ };
+
+ const result = await this.createMessagingProcess(
+ [{ sp_addresses: [this.selectedMemberId!] }],
+ 'relay_address',
+ 1
+ );
+
+ console.log('Final file message process:', {
+ template: messageTemplate,
+ result: result,
+ timestamp: new Date().toISOString()
+ });
const fileInput = this.shadowRoot?.querySelector('#file-input') as HTMLInputElement;
if (fileInput) fileInput.value = '';
- // Générer la réponse automatique
+ this.loadMemberChat(this.selectedMemberId!);
+
setTimeout(() => {
const autoReply = this.generateAutoReply(this.selectedMemberId!);
messageStore.addMessage(this.selectedMemberId!, autoReply);
this.messagesMock = messageStore.getMessages();
this.loadMemberChat(this.selectedMemberId!);
- // Ajouter la notification UNIQUEMENT pour la réponse reçue
this.addNotification(this.selectedMemberId!, autoReply);
}, 1000);
- };
+
+ } catch (error) {
+ console.error('Error sending file:', error);
+ }
+ }
+
+ private async readFileAsBase64(file: File): Promise {
+ return new Promise((resolve, reject) => {
+ const reader = new FileReader();
+ reader.onload = () => resolve(reader.result as string);
+ reader.onerror = reject;
+ reader.readAsDataURL(file);
+ });
+ }
+
+ private async compressImage(file: File): Promise {
+ return new Promise((resolve, reject) => {
+ const img = new Image();
+ const canvas = document.createElement('canvas');
+ const ctx = canvas.getContext('2d');
+
+ img.onload = () => {
+ // Calculer les nouvelles dimensions
+ let width = img.width;
+ let height = img.height;
+ const MAX_WIDTH = 800;
+ const MAX_HEIGHT = 600;
+
+ if (width > height) {
+ if (width > MAX_WIDTH) {
+ height *= MAX_WIDTH / width;
+ width = MAX_WIDTH;
+ }
+ } else {
+ if (height > MAX_HEIGHT) {
+ width *= MAX_HEIGHT / height;
+ height = MAX_HEIGHT;
+ }
+ }
+
+ canvas.width = width;
+ canvas.height = height;
+ ctx?.drawImage(img, 0, 0, width, height);
+
+ // Compression avec qualité réduite
+ resolve(canvas.toDataURL('image/jpeg', 0.7));
+ };
+
+ img.onerror = reject;
+ img.src = URL.createObjectURL(file);
+ });
}
connectedCallback() {