send_file_ok
This commit is contained in:
parent
1b980fd53c
commit
397d32623d
@ -454,7 +454,7 @@ class ChatElement extends HTMLElement {
|
|||||||
messaging_id: processId,
|
messaging_id: processId,
|
||||||
description: 'message_content',
|
description: 'message_content',
|
||||||
metadata: {
|
metadata: {
|
||||||
text: "Je suis un message automatique de réponse<EFBFBD><EFBFBD>",
|
text: "Je suis un message automatique de réponse",
|
||||||
timestamp: timestamp + 1000,
|
timestamp: timestamp + 1000,
|
||||||
sender: this.selectedMemberId,
|
sender: this.selectedMemberId,
|
||||||
recipient: myAddresses[0],
|
recipient: myAddresses[0],
|
||||||
@ -526,14 +526,13 @@ class ChatElement extends HTMLElement {
|
|||||||
chatHeader.textContent = `Chat with ${emojis}`;
|
chatHeader.textContent = `Chat with ${emojis}`;
|
||||||
messagesContainer.innerHTML = '';
|
messagesContainer.innerHTML = '';
|
||||||
|
|
||||||
// Ouvrir IndexedDB
|
|
||||||
const dbRequest = indexedDB.open('4nk');
|
const dbRequest = indexedDB.open('4nk');
|
||||||
|
|
||||||
dbRequest.onerror = () => {
|
dbRequest.onerror = () => {
|
||||||
console.error("Database error:", dbRequest.error);
|
console.error("Database error:", dbRequest.error);
|
||||||
};
|
};
|
||||||
|
|
||||||
dbRequest.onsuccess = (event) => {
|
dbRequest.onsuccess = async (event) => {
|
||||||
const db = dbRequest.result;
|
const db = dbRequest.result;
|
||||||
const transaction = db.transaction(['diffs'], 'readonly');
|
const transaction = db.transaction(['diffs'], 'readonly');
|
||||||
const store = transaction.objectStore('diffs');
|
const store = transaction.objectStore('diffs');
|
||||||
@ -547,7 +546,6 @@ class ChatElement extends HTMLElement {
|
|||||||
if (cursor) {
|
if (cursor) {
|
||||||
const record = cursor.value;
|
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' &&
|
if (record.description === 'message_content' &&
|
||||||
record.metadata &&
|
record.metadata &&
|
||||||
record.metadata.roleName === this.selectedRole &&
|
record.metadata.roleName === this.selectedRole &&
|
||||||
@ -558,7 +556,6 @@ class ChatElement extends HTMLElement {
|
|||||||
}
|
}
|
||||||
cursor.continue();
|
cursor.continue();
|
||||||
} else {
|
} else {
|
||||||
// Trier les messages par timestamp
|
|
||||||
messages.sort((a, b) => a.metadata.timestamp - b.metadata.timestamp);
|
messages.sort((a, b) => a.metadata.timestamp - b.metadata.timestamp);
|
||||||
|
|
||||||
for (const message of messages) {
|
for (const message of messages) {
|
||||||
@ -573,6 +570,39 @@ class ChatElement extends HTMLElement {
|
|||||||
|
|
||||||
const senderEmoji = await addressToEmoji(message.metadata.sender);
|
const senderEmoji = await addressToEmoji(message.metadata.sender);
|
||||||
|
|
||||||
|
// 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 = `
|
messageContent.innerHTML = `
|
||||||
<div class="message-content">
|
<div class="message-content">
|
||||||
<strong>${senderEmoji}</strong>: ${message.metadata.text}
|
<strong>${senderEmoji}</strong>: ${message.metadata.text}
|
||||||
@ -581,6 +611,7 @@ class ChatElement extends HTMLElement {
|
|||||||
${new Date(message.metadata.timestamp).toLocaleString('fr-FR')}
|
${new Date(message.metadata.timestamp).toLocaleString('fr-FR')}
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
messageElement.appendChild(messageContent);
|
messageElement.appendChild(messageContent);
|
||||||
messagesContainer.appendChild(messageElement);
|
messagesContainer.appendChild(messageElement);
|
||||||
@ -589,10 +620,6 @@ class ChatElement extends HTMLElement {
|
|||||||
this.scrollToBottom(messagesContainer);
|
this.scrollToBottom(messagesContainer);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
cursorRequest.onerror = () => {
|
|
||||||
console.error("Error loading messages:", cursorRequest.error);
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} catch (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) {
|
private async toggleMembers(roleData: any, roleElement: HTMLElement) {
|
||||||
let memberList = roleElement.querySelector('.member-list');
|
let memberList = roleElement.querySelector('.member-list');
|
||||||
const roleName = roleElement.querySelector('.role-name')?.textContent || '';
|
const roleName = roleElement.querySelector('.role-name')?.textContent || '';
|
||||||
@ -871,9 +918,7 @@ class ChatElement extends HTMLElement {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
const myAddresses = await this.getMemberFromDevice();
|
const myAddresses = await this.getMemberFromDevice();
|
||||||
if (!myAddresses) {
|
if (!myAddresses) throw new Error('No paired member found');
|
||||||
throw new Error('No paired member found');
|
|
||||||
}
|
|
||||||
|
|
||||||
let fileData: string;
|
let fileData: string;
|
||||||
if (file.type.startsWith('image/')) {
|
if (file.type.startsWith('image/')) {
|
||||||
@ -882,117 +927,102 @@ class ChatElement extends HTMLElement {
|
|||||||
fileData = await this.readFileAsBase64(file);
|
fileData = await this.readFileAsBase64(file);
|
||||||
}
|
}
|
||||||
|
|
||||||
const newMessage = {
|
const timestamp = Date.now();
|
||||||
id: Date.now(),
|
const processId = this.getAttribute('process-id');
|
||||||
sender: myAddresses[0],
|
const uniqueKey = `${processId}${timestamp}`;
|
||||||
text: `Fichier envoyé: ${file.name}`,
|
|
||||||
fileName: file.name,
|
const dbRequest = indexedDB.open('4nk');
|
||||||
time: new Date().toLocaleString('fr-FR'),
|
|
||||||
type: 'file',
|
dbRequest.onerror = (event) => {
|
||||||
class: 'message user'
|
console.error("Database error:", dbRequest.error);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
dbRequest.onsuccess = async (event) => {
|
||||||
|
const db = dbRequest.result;
|
||||||
|
const transaction = db.transaction(['diffs'], 'readwrite');
|
||||||
|
const store = transaction.objectStore('diffs');
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const fileKey = `file_${newMessage.id}`;
|
// Message du fichier
|
||||||
localStorage.setItem(fileKey, fileData);
|
const fileTemplate = {
|
||||||
} catch (storageError) {
|
value_commitment: uniqueKey,
|
||||||
console.error('Erreur de stockage du fichier:', storageError);
|
messaging_id: processId,
|
||||||
alert('Erreur lors du stockage du fichier. Essayez avec un fichier plus petit.');
|
description: 'message_content',
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
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,
|
|
||||||
metadata: {
|
metadata: {
|
||||||
created_at: newMessage.time,
|
text: `Fichier envoyé: ${file.name}`,
|
||||||
last_updated: newMessage.time,
|
timestamp: timestamp,
|
||||||
sender: myAddresses[0],
|
sender: myAddresses[0],
|
||||||
recipient: this.selectedMemberId,
|
recipient: this.selectedMemberId,
|
||||||
|
messageState: this.messageState,
|
||||||
|
roleName: this.selectedRole,
|
||||||
|
type: 'file',
|
||||||
fileName: file.name,
|
fileName: file.name,
|
||||||
fileType: file.type
|
fileType: file.type,
|
||||||
}
|
fileData: fileData
|
||||||
}
|
|
||||||
},
|
|
||||||
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,
|
|
||||||
JSON.stringify(messageTemplate),
|
|
||||||
'file_message'
|
|
||||||
);
|
|
||||||
|
|
||||||
console.log('Final file message process:', {
|
await new Promise<void>((resolve, reject) => {
|
||||||
template: messageTemplate,
|
const request = store.add(fileTemplate);
|
||||||
result: result,
|
request.onsuccess = () => {
|
||||||
timestamp: new Date().toISOString()
|
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;
|
const fileInput = this.shadowRoot?.querySelector('#file-input') as HTMLInputElement;
|
||||||
if (fileInput) fileInput.value = '';
|
if (fileInput) fileInput.value = '';
|
||||||
|
|
||||||
this.loadMemberChat(this.selectedMemberId!);
|
// Recharger les messages
|
||||||
|
if (this.selectedMemberId) {
|
||||||
setTimeout(() => {
|
await this.loadMemberChat(this.selectedMemberId);
|
||||||
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) {
|
} catch (error) {
|
||||||
console.error('Error sending file:', error);
|
console.error('❌ Transaction error:', error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
console.error('❌ Error in sendFile:', error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user