// ECO-PANNEAU.FR - __react/socle/_socle_messagerie_ui.jsx
const { memo, useEffect } = React;
// 1. - UTILITAIRES ET MODALES TRANSVERSES
window.pano_ModerationModal = ({ word, onModify, onRequestControl }) => {
const { ShieldIcon } = window.pano_getIcons();
const { Button, Modal } = window.pano_getComponents();
return (
(
Modifier mon message
Envoyer pour contrôle
)}
>
À cause de l'utilisation de l'expression "{word}" , vous devez modifier votre message.
Vous avez également la possibilité de faire contrôler votre message par le support technique avant envoi au destinataire.
);
};
window.pano_checkForBlacklist = (text, settings) => {
if (!settings || !settings.blacklist) return null;
const words = settings.blacklist.split(',')
.map(w => w.trim().toLowerCase())
.filter(w => w);
const lowerText = text.toLowerCase();
for (let w of words) {
if (lowerText.includes(w)) return w;
}
return null;
};
// 2. - COMPOSANT : BULLE DE MESSAGE (MÉMORISÉE POUR PERFORMANCES)
window.pano_MessageBubble = memo(({ msg, isMe, displayAuthor, onImageLoad, onViewAttachment, isAdmin, onModerate, themeColor = '#059669', onAction, canDeleteAttachment, onDeleteAttachment }) => {
const { AlertTriangleIcon, LoaderIcon, FileTextIcon, EditIcon, CheckCircleIcon, Trash2Icon } = window.pano_getIcons();
const { Button, PdfThumbnail } = window.pano_getComponents();
useEffect(() => {
if (!window.DOMPurify && window.pano_logFallback) {
window.pano_logFallback("DOMPurify introuvable dans MessageBubble. Utilisation du fallback regex pour la sécurisation HTML.");
}
}, []);
const attachments = [];
const deletedAttachments = [];
// Capture des pièces jointes valides
const regex = /\[ATTACHMENT:([a-zA-Z0-9_.\/-]+):(image|pdf)(?::(\d+))?\]/g;
let match;
while ((match = regex.exec(msg.detail || '')) !== null) {
attachments.push({ id: match[1], type: match[2], numPages: match[3] ? parseInt(match[3], 10) : 1 });
}
// Capture robuste des pièces jointes supprimées
const delRegex = /\[DELETED_ATTACHMENT(?::(image|pdf))?\]/g;
let delMatch;
while ((delMatch = delRegex.exec(msg.detail || '')) !== null) {
deletedAttachments.push({ type: delMatch[1] || 'fichier' });
}
// Nettoyage complet du texte
const textContent = (msg.detail || '').replace(regex, '').replace(delRegex, '').trim();
const isHtmlAllowed = msg.authorType === 'Admin' || msg.authorType === 'Système' || msg.authorType === 'Systeme' || msg.authorType === 'System';
const suspendRegex = /Le panneau "([^"]+)" a été (?:suspendu|rejeté)/i;
const suspendMatch = textContent.match(suspendRegex);
const isTemp = msg.id.toString().startsWith('temp_');
const handleCorrigerClick = (e) => {
e.preventDefault();
// Délégation propre de l'action au composant parent
if (onAction && suspendMatch) {
onAction('correct_panel', suspendMatch[1]);
}
};
const handleHtmlClick = (e) => {
const grantBtn = e.target.closest('[data-action="grant_access"]');
if (grantBtn) {
e.preventDefault();
e.stopPropagation();
window.dispatchEvent(new CustomEvent('chat_grant_access'));
}
};
return (
{msg.isAlert === 2 && (
En attente de contrôle
{isAdmin && onModerate && (
onModerate(msg.id, 'approve')} className="py-1 px-2 text-[9px] h-auto min-h-0 shadow-none rounded-md" icon={CheckCircleIcon}>
Valider
onModerate(msg.id, 'reject')} className="p-1 h-auto min-h-0 shadow-none" icon={Trash2Icon} title="Rejeter" />
)}
)}
{textContent && (
isHtmlAllowed ? (
/g, '>').replace(/"/g, '"').replace(/'/g, ''')
}}
className="text-sm leading-relaxed whitespace-pre-wrap admin-html break-words"
/>
) : (
{textContent}
)
)}
{suspendMatch && msg.authorType === 'Admin' && !isMe && (
Corriger le panneau
)}
{attachments.length > 0 && (
{attachments.map((att, i) => (
{att.type === 'image' && (
onViewAttachment(att)} className="cursor-pointer">
{/* ZÉRO-DETTE : Utilisation de preview=1 pour les images */}
{canDeleteAttachment && onDeleteAttachment && (
{ e.stopPropagation(); onDeleteAttachment(msg.id, att.id, att.type); }}
className="absolute top-1 right-1 opacity-0 group-hover:opacity-100 transition-all shadow-md p-1.5 w-7 h-7"
title="Supprimer cette pièce jointe (Libérer de l'espace)"
/>
)}
)}
{att.type === 'pdf' && PdfThumbnail && (
onViewAttachment(att)} className={`cursor-pointer rounded-xl border flex flex-col text-left transition-transform hover:scale-[1.02] h-full ${isMe ? 'border-white/20 bg-black/10' : 'border-slate-200 bg-white'}`}>
Aperçu PDF
{canDeleteAttachment && onDeleteAttachment && (
{ e.stopPropagation(); onDeleteAttachment(msg.id, att.id, att.type); }}
className="absolute top-1 right-1 opacity-0 group-hover:opacity-100 transition-all shadow-md p-1.5 w-7 h-7"
title="Supprimer cette pièce jointe (Libérer de l'espace)"
/>
)}
)}
))}
)}
{/* Affichage des pièces jointes supprimées */}
{deletedAttachments.length > 0 && (
0 ? 'pt-2 border-t border-white/10' : ''}`}>
{deletedAttachments.map((att, i) => (
Fichier supprimé par l'utilisateur pour libérer de l'espace.
))}
)}
{/* CORRECTION UX : Modification de l'horodatage pour l'envoi en cours */}
{displayAuthor} • {isTemp ? Envoi en cours... : new Date(String(msg.created_at || '').replace(' ', 'T')).toLocaleString('fr-FR')}
{isTemp && }
);
}, (prevProps, nextProps) => {
return prevProps.msg.id === nextProps.msg.id &&
prevProps.msg.resolved === nextProps.msg.resolved &&
prevProps.msg.isAlert === nextProps.msg.isAlert &&
prevProps.isAdmin === nextProps.isAdmin &&
prevProps.themeColor === nextProps.themeColor;
});
/* EOF ========== [__react/socle/_socle_messagerie_ui.jsx] */