send_file_ok
This commit is contained in:
parent
1b980fd53c
commit
397d32623d
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user