mirror of
https://github.com/R0m1k3/Loki.git
synced 2026-10-23 15:08:16 +02:00
Images du fil : miniatures des deux côtés, loupe au clic
Une pièce jointe n'affichait que son nom de fichier, et une image posée par l'IA sortait à sa taille NATIVE — .chatimg portait la classe mais aucune règle CSS, donc une capture remplissait la colonne et poussait le texte hors de vue. - pièce jointe image : vignette dans le composeur (objectURL local, rien n'est encore parti au serveur) et tuile 200x160 dans le message envoyé, hydratée comme les captures (fetch authentifié + blob:) ; - images de l'IA plafonnées à 280px de haut ; - clic sur n'importe quelle image = loupe plein écran (Échap ou clic sur le fond pour fermer). La source est relue AU CLIC, l'hydratation remplaçant le src par un blob: après coup. align-items:flex-start sur .msg-files au passage : une pastille texte voisine d'une vignette s'étirait à sa hauteur et, arrondie à 999px, devenait un gros ovale. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
781520afd8
commit
88e1b38582
5 files changed
+310
-10
No files matched your search
@@ -0,0 +1,58 @@
|
||||
// ===== Loupe d'image =======================================================
|
||||
// Les images du fil sont PLAFONNÉES (CSS .chatimg / .msg-img) : sans plafond,
|
||||
// une capture sortait à sa taille native et mangeait tout l'écran, ce qui rendait
|
||||
// la conversation illisible. Le plafond ne se paie donc pas en information : un
|
||||
// clic rouvre l'image ici, aussi grande que la fenêtre le permet.
|
||||
//
|
||||
// On réutilise la source DÉJÀ chargée par la vignette (blob: hydraté par
|
||||
// hydrateImages, ou objectURL local d'une pièce jointe en attente) : rien n'est
|
||||
// re-téléchargé, et ça marche derrière la clé de pilotage — qu'une balise <img>
|
||||
// ne sait pas porter, d'où le blob: en premier lieu.
|
||||
function lightboxEl(){
|
||||
let el=document.getElementById('lightbox');
|
||||
if(el) return el;
|
||||
el=document.createElement('div');
|
||||
el.id='lightbox';
|
||||
el.innerHTML='<button type="button" class="lb-x" title="fermer" aria-label="fermer">×</button>'
|
||||
+'<img alt=""><div class="lb-name"></div>';
|
||||
// Clic sur le FOND (ou sur le ×) = fermer ; clic sur l'image = ne rien faire,
|
||||
// sinon on referme dès qu'on veut la regarder de près.
|
||||
el.onclick=e=>{ if(e.target===el || e.target.classList.contains('lb-x')) closeLightbox(); };
|
||||
document.body.appendChild(el);
|
||||
return el;
|
||||
}
|
||||
// Capture (3e argument à true) : sans elle, Échap serait d'abord vu par les
|
||||
// écouteurs des modales déjà en place et la loupe ne se fermerait pas.
|
||||
function _lbKey(e){
|
||||
if(e.key==='Escape'){ e.preventDefault(); e.stopPropagation(); closeLightbox(); }
|
||||
}
|
||||
function openLightbox(src, name){
|
||||
if(!src) return;
|
||||
const el=lightboxEl(), img=el.querySelector('img');
|
||||
img.src=src;
|
||||
img.alt=name||'';
|
||||
el.querySelector('.lb-name').textContent=name||'';
|
||||
showModal(el);
|
||||
document.addEventListener('keydown', _lbKey, true);
|
||||
}
|
||||
function closeLightbox(){
|
||||
const el=document.getElementById('lightbox'); if(!el) return;
|
||||
document.removeEventListener('keydown', _lbKey, true);
|
||||
hideModal(el);
|
||||
// La source n'est lâchée qu'APRÈS la transition : la vider tout de suite
|
||||
// laissait un cadre vide clignoter pendant la fermeture.
|
||||
setTimeout(()=>{
|
||||
if(!el.classList.contains('show')) el.querySelector('img').removeAttribute('src');
|
||||
}, 200);
|
||||
}
|
||||
// Rend une image cliquable (idempotent : renderBody reconstruit le DOM à chaque
|
||||
// delta du streaming, et hydrateImages nous rappelle sur les mêmes éléments).
|
||||
//
|
||||
// On lit currentSrc/src AU CLIC et non à la liaison : l'hydratation remplace la
|
||||
// source par un blob: après coup, et figer l'URL /api/chat/image ici rouvrirait
|
||||
// une image que le navigateur n'a pas le droit de charger seul.
|
||||
function bindZoom(img, name){
|
||||
if(!img || img.dataset.zoom) return;
|
||||
img.dataset.zoom='1';
|
||||
img.addEventListener('click', ()=>openLightbox(img.currentSrc||img.src, name||img.alt||''));
|
||||
}
|
||||
Reference in new issue
Block a user