133 lines
5.5 KiB
JavaScript
133 lines
5.5 KiB
JavaScript
/* ALFRED_HIDE_HERMES_ACTIVITY_V2
|
|
Supprime uniquement l'ancienne vue "Activité Hermes" du DOM visuel.
|
|
N'interrompt ni les taches de fond, ni le MCP, ni les evenements Socket.IO.
|
|
*/
|
|
(() => {
|
|
'use strict';
|
|
|
|
const TITLE = /\bactivit[eé]\s+hermes\b/i;
|
|
const EXACT_TITLE = /^\s*[⌄˅∨▾▿▼v]?\s*activit[eé]\s+hermes\s*(?:\d+)?\s*$/i;
|
|
const SPECIFIC_SELECTOR = [
|
|
'#hermesActivityPopup', '#hermesActivityModal',
|
|
'[aria-label="Activité Hermes"]', '[aria-label="Activite Hermes"]',
|
|
'[data-component="hermes-activity"]', '[data-widget="hermes-activity"]',
|
|
'.hermes-activity-panel', '.hermes-activity-popup',
|
|
'.hermes-activity-widget', '.hermes-activity-dock',
|
|
'.hermes-task-panel', '.hermes-tasks-panel'
|
|
].join(',');
|
|
const CLASS_HINT = /(?:hermes.{0,30}(?:activit|activity|tasks?|jobs?)|(?:activit|activity|tasks?|jobs?).{0,30}hermes)/i;
|
|
const PANEL_HINT = /(?:activit|activity|tasks?|jobs?|queue|history|panel|widget|dock|drawer|popover|sidebar)/i;
|
|
|
|
function markHidden(element) {
|
|
if (!element || !element.isConnected || element === document.body) return;
|
|
if (!element.hasAttribute('data-alfred-hermes-hidden')) {
|
|
element.setAttribute('data-alfred-hermes-hidden', 'true');
|
|
}
|
|
// Important : certains widgets reinitialisent leur attribut hidden ou display.
|
|
if (!element.hidden) element.hidden = true;
|
|
if (element.style.getPropertyValue('display') !== 'none' ||
|
|
element.style.getPropertyPriority('display') !== 'important') {
|
|
element.style.setProperty('display', 'none', 'important');
|
|
}
|
|
}
|
|
|
|
function isTitle(text) {
|
|
return EXACT_TITLE.test(String(text || '').replace(/\u00a0/g, ' ').trim());
|
|
}
|
|
|
|
function isSafeCandidate(el) {
|
|
if (!el || !el.isConnected) return false;
|
|
if (el.matches('html,body,main,.alfred-shell,#stage,#content')) return false;
|
|
if (el.contains(document.querySelector('#stage')) && document.querySelector('#stage')) return false;
|
|
if (el.contains(document.querySelector('#alfredTimersDock')) && document.querySelector('#alfredTimersDock')) return false;
|
|
return true;
|
|
}
|
|
|
|
function choosePanel(titleNode) {
|
|
// La capture montre un dock : le titre est accompagne d'un compteur et
|
|
// d'une carte de tache (badge "Termine", bouton "Lire").
|
|
const ancestors = [];
|
|
let el = titleNode.nodeType === 1 ? titleNode : titleNode.parentElement;
|
|
for (let depth = 0; el && depth < 10; depth++, el = el.parentElement) {
|
|
if (!isSafeCandidate(el)) break;
|
|
ancestors.push(el);
|
|
}
|
|
if (!ancestors.length) return null;
|
|
|
|
// Quand l'identifiant ou la classe indiquent explicitement le widget,
|
|
// ces conteneurs sont preferes au contenu de la carte.
|
|
for (const candidate of ancestors) {
|
|
const identity = `${candidate.id || ''} ${typeof candidate.className === 'string' ? candidate.className : ''}`;
|
|
if (CLASS_HINT.test(identity)) return candidate;
|
|
if (candidate.matches('[role="dialog"],[role="complementary"]') && TITLE.test(candidate.textContent || '')) return candidate;
|
|
}
|
|
|
|
// Cas general (et cas de la capture) : choisir le plus petit ancetre
|
|
// suffisamment grand pour contenir l'entete ET la liste des taches.
|
|
for (const candidate of ancestors) {
|
|
const allText = (candidate.innerText || candidate.textContent || '').trim();
|
|
if (allText.length > 15000) continue; // l'ancetre contient deja le titre detecte
|
|
const hasTask = /\b(?:termin[eé]|en\s+cours|en\s+attente|erreur|lire|annuler|rapport)\b/i.test(allText);
|
|
const childCount = candidate.children ? candidate.children.length : 0;
|
|
if (!hasTask || childCount < 2) continue;
|
|
const rect = candidate.getBoundingClientRect();
|
|
if (rect.width >= 180 && rect.height >= 100 &&
|
|
rect.width <= Math.max(window.innerWidth * 0.82, 600) &&
|
|
rect.height <= window.innerHeight * 1.5) {
|
|
return candidate;
|
|
}
|
|
}
|
|
|
|
// Panneau vide : se baser sur la bordure/classe du conteneur, sans cacher
|
|
// un parent generic (page entiere, scene, panneau de transcription).
|
|
for (const candidate of ancestors) {
|
|
const identity = `${candidate.id || ''} ${typeof candidate.className === 'string' ? candidate.className : ''}`;
|
|
if (!PANEL_HINT.test(identity)) continue;
|
|
const rect = candidate.getBoundingClientRect();
|
|
if (rect.width >= 150 && rect.width <= Math.max(window.innerWidth * 0.82, 600)) return candidate;
|
|
}
|
|
return null;
|
|
}
|
|
|
|
function hideActivity() {
|
|
for (const el of document.querySelectorAll(SPECIFIC_SELECTOR)) {
|
|
if (isSafeCandidate(el)) markHidden(el);
|
|
}
|
|
const walker = document.createTreeWalker(document.body, NodeFilter.SHOW_TEXT);
|
|
let textNode;
|
|
while ((textNode = walker.nextNode())) {
|
|
if (!textNode.parentElement || textNode.parentElement.closest('[data-alfred-hermes-hidden]')) continue;
|
|
if (!isTitle(textNode.nodeValue)) continue;
|
|
const panel = choosePanel(textNode);
|
|
if (panel) markHidden(panel);
|
|
}
|
|
}
|
|
|
|
let queued = false;
|
|
function scheduleHide() {
|
|
if (queued) return;
|
|
queued = true;
|
|
queueMicrotask(() => {
|
|
queued = false;
|
|
if (document.body) hideActivity();
|
|
});
|
|
}
|
|
if (document.readyState === 'loading') {
|
|
document.addEventListener('DOMContentLoaded', () => {
|
|
hideActivity();
|
|
observe();
|
|
}, {once:true});
|
|
} else {
|
|
hideActivity();
|
|
observe();
|
|
}
|
|
function observe() {
|
|
const observer = new MutationObserver(scheduleHide);
|
|
observer.observe(document.body, {
|
|
childList: true,
|
|
subtree: true,
|
|
characterData: true
|
|
});
|
|
}
|
|
})();
|