62 lines
8.6 KiB
JavaScript
62 lines
8.6 KiB
JavaScript
/* DONA_FILES_V91 — documents et images, contenu affiché exclusivement avec textContent. */
|
||
(()=>{
|
||
'use strict';
|
||
if(window.DonaFilesV91)return;
|
||
const $=id=>document.getElementById(id);
|
||
const el=(tag,cls,text)=>{const n=document.createElement(tag);if(cls)n.className=cls;if(text!==undefined)n.textContent=String(text);return n;};
|
||
const button=(text,fn,cls='df-button')=>{const b=el('button',cls,text);b.type='button';b.addEventListener('click',fn);return b;};
|
||
let active=null, busy=false, previewURL=null;
|
||
function status(text){if($('dfStatus'))$('dfStatus').textContent=String(text||'');}
|
||
function setBusy(val){busy=val;for(const id of ['dfUpload','dfAnalyze','dfDrop','dfDelete']){const n=$(id);if(n)n.disabled=val;}}
|
||
async function postJson(path,data){const response=await fetch(path,{method:'POST',credentials:'same-origin',headers:{'Content-Type':'application/json','X-Alfred-Request':'1'},body:JSON.stringify(data)});const obj=await response.json().catch(()=>({}));if(!response.ok||obj.ok===false)throw Error(obj.error||'Erreur HTTP '+response.status);return obj;}
|
||
function open(){if(!$('donaFilesV91'))init();$('donaFilesV91').hidden=false;document.body.classList.add('df-open');}
|
||
function close(){if(busy)return;$('donaFilesV91').hidden=true;document.body.classList.remove('df-open');}
|
||
function showAttachment(info,file){active=info;$('dfName').textContent=info.filename+' · '+(Math.round(info.size/1024))+' Ko';$('dfCurrent').hidden=false;$('dfEmpty').hidden=true;$('dfAnswer').textContent='';$('dfQuestion').value=info.kind==='image'?'Que vois-tu sur cette image ?':'Fais un résumé clair de ce document.';
|
||
if(previewURL){URL.revokeObjectURL(previewURL);previewURL=null;}const picture=$('dfPreview');picture.hidden=true;picture.removeAttribute('src');
|
||
if(info.kind==='image'&&file){previewURL=URL.createObjectURL(file);picture.src=previewURL;picture.hidden=false;}status('Fichier prêt. Tu peux demander une analyse.');}
|
||
async function upload(file){if(!file||busy)return;if(file.size>10*1024*1024){status('Taille maximale : 10 Mo.');return;}setBusy(true);status('Téléversement…');try{const form=new FormData();form.append('file',file,file.name);const response=await fetch('/api/dona/files/upload',{method:'POST',credentials:'same-origin',headers:{'X-Alfred-Request':'1'},body:form});const obj=await response.json().catch(()=>({}));if(!response.ok||obj.ok===false)throw Error(obj.error||'Téléversement impossible.');const previous=active;showAttachment(obj,file);if(previous&&previous.id!==obj.id)postJson('/api/dona/files/delete',{id:previous.id}).catch(()=>{});}catch(e){status('Erreur : '+e.message);}finally{setBusy(false);}}
|
||
async function analyze(){if(!active||busy){status('Ajoute d’abord un fichier.');return;}const question=String($('dfQuestion').value||'').trim();if(!question){status('Saisis une question.');return;}setBusy(true);status('Hermes analyse le fichier…');$('dfAnswer').textContent='';try{const result=await postJson('/api/dona/files/analyze',{id:active.id,question});$('dfAnswer').textContent=result.answer||'Aucune réponse.';status('Analyse terminée.');}catch(e){status('Erreur : '+e.message);}finally{setBusy(false);}}
|
||
async function remove(){if(!active||busy)return;setBusy(true);try{await postJson('/api/dona/files/delete',{id:active.id});active=null;$('dfCurrent').hidden=true;$('dfEmpty').hidden=false;$('dfAnswer').textContent='';$('dfName').textContent='';$('dfInput').value='';status('Fichier effacé.');if(previewURL){URL.revokeObjectURL(previewURL);previewURL=null;}}catch(e){status(e.message);}finally{setBusy(false);}}
|
||
function init(){if($('donaFilesV91'))return;const overlay=el('div','df-overlay');overlay.id='donaFilesV91';overlay.hidden=true;const panel=el('section','df-panel');panel.setAttribute('role','dialog');panel.setAttribute('aria-modal','true');panel.setAttribute('aria-label','Analyser un fichier avec Dona');
|
||
const head=el('div','df-head');const heading=el('div');heading.append(el('span','df-eyebrow','DONA · PIÈCES JOINTES'),el('h2','','Analyser un document ou une photo'));head.append(heading,button('×',close,'df-close'));panel.append(head);
|
||
const help=el('p','df-hint','PDF, Word (.docx), texte, Markdown, JPEG, PNG et WebP · 10 Mo max · Conservation temporaire 30 minutes · Pas d’indexation automatique.');panel.append(help);
|
||
const zone=el('div','df-drop');zone.id='dfDrop';zone.setAttribute('role','group');zone.append(el('span','df-upload-icon','📎'),el('strong','','Dépose ton fichier ici ou sélectionne-le'));
|
||
const fileInput=el('input','df-file');fileInput.type='file';fileInput.id='dfInput';fileInput.accept='.pdf,.docx,.txt,.md,.jpg,.jpeg,.png,.webp';fileInput.addEventListener('change',()=>{if(fileInput.files?.[0])upload(fileInput.files[0]);});zone.append(fileInput);
|
||
const choose=button('Choisir un fichier',()=>fileInput.click(),'df-button df-primary');choose.id='dfUpload';zone.append(choose);zone.addEventListener('dragover',e=>{e.preventDefault();zone.classList.add('df-over');});zone.addEventListener('dragleave',()=>zone.classList.remove('df-over'));zone.addEventListener('drop',e=>{e.preventDefault();zone.classList.remove('df-over');if(e.dataTransfer.files?.[0])upload(e.dataTransfer.files[0]);});panel.append(zone);
|
||
const empty=el('p','df-hint','Aucun fichier sélectionné.');empty.id='dfEmpty';panel.append(empty);
|
||
const current=el('div','df-current');current.id='dfCurrent';current.hidden=true;const filename=el('div','df-filename');filename.id='dfName';const preview=el('img','df-preview');preview.id='dfPreview';preview.alt='Aperçu du fichier image sélectionné';preview.hidden=true;current.append(filename,preview);const del=button('Supprimer cette pièce jointe',remove,'df-button df-del');del.id='dfDelete';current.append(del);panel.append(current);
|
||
const label=el('label','df-label','Que veux-tu savoir ?');label.setAttribute('for','dfQuestion');panel.append(label);const question=el('textarea','df-question');question.id='dfQuestion';question.rows=3;question.maxLength=1200;question.placeholder='Résume ce document, explique les points importants, analyse cette photo…';panel.append(question);
|
||
const examples=el('div','df-examples');[['Résumé','Fais un résumé clair de ce document.'],['Points clés','Quels sont les points importants à retenir ?'],['Analyser','Analyse ce fichier et explique-moi ce qu’il contient.'],['Explication','Explique le contenu simplement.']].forEach(([name,q])=>examples.append(button(name,()=>{question.value=q;},'df-chip')));panel.append(examples);
|
||
const run=button('Analyser avec Hermes',analyze,'df-button df-primary df-run');run.id='dfAnalyze';panel.append(run);
|
||
const msg=el('p','df-status');msg.id='dfStatus';msg.setAttribute('role','status');panel.append(msg);
|
||
const result=el('div','df-answer');result.id='dfAnswer';result.setAttribute('aria-live','polite');panel.append(result);
|
||
panel.append(el('p','df-hint','Dona garde les fichiers en RAM 30 min ; Hermes peut conserver des traces de session. Le fournisseur IA utilisé dépend de la configuration Hermes. Vérifie-la avant d’envoyer des documents confidentiels. Les PDF scannés sans texte ne sont pas encore pris en charge.'));
|
||
overlay.append(panel);document.body.append(overlay);overlay.addEventListener('click',e=>{if(e.target===overlay)close();});document.addEventListener('keydown',e=>{if(e.key==='Escape'&&!overlay.hidden)close();});
|
||
// DONA_FILES_V911_COMPOSE : 📎 à droite du bouton d'envoi de « Écrire à Dona ».
|
||
// Bouton de type button pour ne jamais soumettre le formulaire lors de son activation.
|
||
function mountComposeAttachment(){
|
||
const send=$('donaComposeSend');
|
||
if(!send || !send.closest('.dona-compose-row'))return false;
|
||
let launch=$('dfOpen');
|
||
if(!launch){launch=button('📎',open,'df-compose-attach');launch.id='dfOpen';}
|
||
launch.type='button';
|
||
launch.classList.remove('av-round','df-launch');
|
||
launch.classList.add('df-compose-attach');
|
||
launch.title='Joindre un fichier à Dona';
|
||
launch.setAttribute('aria-label','Joindre un document ou une photo');
|
||
send.insertAdjacentElement('afterend',launch);
|
||
return true;
|
||
}
|
||
if(!mountComposeAttachment()){
|
||
let count=0;
|
||
const timer=setInterval(()=>{
|
||
if(mountComposeAttachment() || ++count>100)clearInterval(timer);
|
||
},150);
|
||
}
|
||
const v9quick=document.querySelector('#donaSuiteV9 .dv9-quick');if(v9quick)v9quick.append(button('📎 Analyser un fichier',()=>{if(window.DonaSuiteV9?.close)window.DonaSuiteV9.close();open();},'dv9-chip'));
|
||
window.alfredSocket?.on('dona_files_v91_result',result=>{if(result?.answer&&active?.id===result.id){$('dfAnswer').textContent=result.answer;status('Analyse vocale terminée.');}});
|
||
}
|
||
if(document.readyState==='loading')document.addEventListener('DOMContentLoaded',init,{once:true});else init();
|
||
window.DonaFilesV91={open,close};
|
||
})();
|