send_file_ok

This commit is contained in:
Pascal 2025-01-14 14:21:19 +01:00
parent 1b980fd53c
commit 397d32623d

View File

@ -454,7 +454,7 @@ class ChatElement extends HTMLElement {
messaging_id: processId,
description: 'message_content',
metadata: {
text: "Je suis un message automatique de réponse<EFBFBD><EFBFBD>",
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 = `
<div class="message-content">
<strong>${senderEmoji}</strong>: ${message.metadata.text}
</div>
<div class="message-time">
${new Date(message.metadata.timestamp).toLocaleString('fr-FR')}
</div>
`;
// Vérifier si c'est un fichier
if (message.metadata.type === 'file') {
let fileContent = '';
if (message.metadata.fileType.startsWith('image/')) {
// Afficher l'image
fileContent = `
<div class="file-preview">
<img src="${message.metadata.fileData}" alt="${message.metadata.fileName}" style="max-width: 200px; max-height: 200px;"/>
</div>
`;
} 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 = `
<div class="file-download">
<a href="${url}" download="${message.metadata.fileName}">
📎 ${message.metadata.fileName}
</a>
</div>
`;
}
messageContent.innerHTML = `
<div class="message-content">
<strong>${senderEmoji}</strong>: ${fileContent}
</div>
<div class="message-time">
${new Date(message.metadata.timestamp).toLocaleString('fr-FR')}
</div>
`;
} else {
// Message texte normal
messageContent.innerHTML = `
<div class="message-content">
<strong>${senderEmoji}</strong>: ${message.metadata.text}
</div>
<div class="message-time">
${new Date(message.metadata.timestamp).toLocaleString('fr-FR')}
</div>
`;
}
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<void>((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<void>((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<void>((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);
}
}