diff --git a/src/pages/chat/chat.ts b/src/pages/chat/chat.ts
index 15be721..9629ad4 100755
--- a/src/pages/chat/chat.ts
+++ b/src/pages/chat/chat.ts
@@ -454,7 +454,7 @@ class ChatElement extends HTMLElement {
messaging_id: processId,
description: 'message_content',
metadata: {
- text: "Je suis un message automatique de réponse��",
+ text: "Je suis un message automatique de réponse",
timestamp: timestamp + 1000,
sender: this.selectedMemberId,
recipient: myAddresses[0],
@@ -526,14 +526,13 @@ class ChatElement extends HTMLElement {
chatHeader.textContent = `Chat with ${emojis}`;
messagesContainer.innerHTML = '';
- // Ouvrir IndexedDB
const dbRequest = indexedDB.open('4nk');
dbRequest.onerror = () => {
console.error("Database error:", dbRequest.error);
};
- dbRequest.onsuccess = (event) => {
+ dbRequest.onsuccess = async (event) => {
const db = dbRequest.result;
const transaction = db.transaction(['diffs'], 'readonly');
const store = transaction.objectStore('diffs');
@@ -547,7 +546,6 @@ class ChatElement extends HTMLElement {
if (cursor) {
const record = cursor.value;
- // Vérifier si c'est un message valide avec le bon role et les bons participants
if (record.description === 'message_content' &&
record.metadata &&
record.metadata.roleName === this.selectedRole &&
@@ -558,7 +556,6 @@ class ChatElement extends HTMLElement {
}
cursor.continue();
} else {
- // Trier les messages par timestamp
messages.sort((a, b) => a.metadata.timestamp - b.metadata.timestamp);
for (const message of messages) {
@@ -573,14 +570,48 @@ class ChatElement extends HTMLElement {
const senderEmoji = await addressToEmoji(message.metadata.sender);
- messageContent.innerHTML = `
-
- ${senderEmoji}: ${message.metadata.text}
-
-
- ${new Date(message.metadata.timestamp).toLocaleString('fr-FR')}
-
- `;
+ // Vérifier si c'est un fichier
+ if (message.metadata.type === 'file') {
+ let fileContent = '';
+ if (message.metadata.fileType.startsWith('image/')) {
+ // Afficher l'image
+ fileContent = `
+
+

+
+ `;
+ } else {
+ // Afficher un lien pour télécharger le fichier
+ const blob = this.base64ToBlob(message.metadata.fileData, message.metadata.fileType);
+ const url = URL.createObjectURL(blob);
+ fileContent = `
+
+ `;
+ }
+
+ messageContent.innerHTML = `
+
+ ${senderEmoji}: ${fileContent}
+
+
+ ${new Date(message.metadata.timestamp).toLocaleString('fr-FR')}
+
+ `;
+ } else {
+ // Message texte normal
+ messageContent.innerHTML = `
+
+ ${senderEmoji}: ${message.metadata.text}
+
+
+ ${new Date(message.metadata.timestamp).toLocaleString('fr-FR')}
+
+ `;
+ }
messageElement.appendChild(messageContent);
messagesContainer.appendChild(messageElement);
@@ -589,10 +620,6 @@ class ChatElement extends HTMLElement {
this.scrollToBottom(messagesContainer);
}
};
-
- cursorRequest.onerror = () => {
- console.error("Error loading messages:", cursorRequest.error);
- };
};
} catch (error) {
@@ -600,6 +627,26 @@ class ChatElement extends HTMLElement {
}
}
+ // Ajouter cette méthode utilitaire pour convertir base64 en Blob
+ private base64ToBlob(base64: string, type: string): Blob {
+ const byteCharacters = atob(base64.split(',')[1]);
+ const byteArrays = [];
+
+ for (let offset = 0; offset < byteCharacters.length; offset += 512) {
+ const slice = byteCharacters.slice(offset, offset + 512);
+ const byteNumbers = new Array(slice.length);
+
+ for (let i = 0; i < slice.length; i++) {
+ byteNumbers[i] = slice.charCodeAt(i);
+ }
+
+ const byteArray = new Uint8Array(byteNumbers);
+ byteArrays.push(byteArray);
+ }
+
+ return new Blob(byteArrays, { type: type });
+ }
+
private async toggleMembers(roleData: any, roleElement: HTMLElement) {
let memberList = roleElement.querySelector('.member-list');
const roleName = roleElement.querySelector('.role-name')?.textContent || '';
@@ -871,9 +918,7 @@ class ChatElement extends HTMLElement {
try {
const myAddresses = await this.getMemberFromDevice();
- if (!myAddresses) {
- throw new Error('No paired member found');
- }
+ if (!myAddresses) throw new Error('No paired member found');
let fileData: string;
if (file.type.startsWith('image/')) {
@@ -882,117 +927,102 @@ class ChatElement extends HTMLElement {
fileData = await this.readFileAsBase64(file);
}
- const newMessage = {
- id: Date.now(),
- sender: myAddresses[0],
- text: `Fichier envoyé: ${file.name}`,
- fileName: file.name,
- time: new Date().toLocaleString('fr-FR'),
- type: 'file',
- class: 'message user'
+ const timestamp = Date.now();
+ const processId = this.getAttribute('process-id');
+ const uniqueKey = `${processId}${timestamp}`;
+
+ const dbRequest = indexedDB.open('4nk');
+
+ dbRequest.onerror = (event) => {
+ console.error("Database error:", dbRequest.error);
};
- 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;
- }
+ dbRequest.onsuccess = async (event) => {
+ const db = dbRequest.result;
+ const transaction = db.transaction(['diffs'], 'readwrite');
+ const store = transaction.objectStore('diffs');
- if (this.selectedMemberId) {
- messageStore.addMessage(this.selectedMemberId, newMessage);
- this.messagesMock = messageStore.getMessages();
- }
-
- 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,
+ try {
+ // Message du fichier
+ const fileTemplate = {
+ value_commitment: uniqueKey,
+ messaging_id: processId,
+ description: 'message_content',
metadata: {
- created_at: newMessage.time,
- last_updated: newMessage.time,
+ text: `Fichier envoyé: ${file.name}`,
+ timestamp: timestamp,
sender: myAddresses[0],
recipient: this.selectedMemberId,
+ messageState: this.messageState,
+ roleName: this.selectedRole,
+ type: 'file',
fileName: file.name,
- fileType: file.type
+ fileType: file.type,
+ fileData: fileData
}
+ };
+
+ await new Promise((resolve, reject) => {
+ const request = store.add(fileTemplate);
+ request.onsuccess = () => {
+ console.log('✅ File message saved');
+ resolve();
+ };
+ request.onerror = () => reject(request.error);
+ });
+
+ // Réponse automatique
+ const autoReplyTemplate = {
+ value_commitment: `${processId}${timestamp + 1000}`,
+ messaging_id: processId,
+ description: 'message_content',
+ metadata: {
+ text: "J'ai bien reçu votre fichier 📎",
+ timestamp: timestamp + 1000,
+ sender: this.selectedMemberId,
+ recipient: myAddresses[0],
+ messageState: this.messageState,
+ roleName: this.selectedRole
+ }
+ };
+
+ await new Promise((resolve, reject) => {
+ const request = store.add(autoReplyTemplate);
+ request.onsuccess = () => {
+ console.log('✅ Auto reply saved');
+ if (myAddresses[0]) {
+ this.addNotification(myAddresses[0], autoReplyTemplate);
+ }
+ resolve();
+ };
+ request.onerror = () => reject(request.error);
+ });
+
+ // Attendre la fin de la transaction
+ await new Promise((resolve, reject) => {
+ transaction.oncomplete = () => {
+ console.log('✅ Transaction completed');
+ resolve();
+ };
+ transaction.onerror = () => reject(transaction.error);
+ });
+
+ // Réinitialiser l'input file
+ const fileInput = this.shadowRoot?.querySelector('#file-input') as HTMLInputElement;
+ if (fileInput) fileInput.value = '';
+
+ // Recharger les messages
+ if (this.selectedMemberId) {
+ await this.loadMemberChat(this.selectedMemberId);
}
- },
- 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]
- }
+
+ } catch (error) {
+ console.error('❌ Transaction error:', error);
}
};
- const result = await this.createMessagingProcess(
- [{ sp_addresses: [this.selectedMemberId!] }],
- 'relay_address',
- 1,
- JSON.stringify(messageTemplate),
- 'file_message'
- );
-
- 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 = '';
-
- this.loadMemberChat(this.selectedMemberId!);
-
- setTimeout(() => {
- const autoReply = this.generateAutoReply(this.selectedMemberId!);
- messageStore.addMessage(this.selectedMemberId!, autoReply);
- this.messagesMock = messageStore.getMessages();
- this.loadMemberChat(this.selectedMemberId!);
-
- this.addNotification(this.selectedMemberId!, autoReply);
- }, 1000);
} catch (error) {
- console.error('Error sending file:', error);
+ console.error('❌ Error in sendFile:', error);
}
}