fix(web): repeindre les terminaux au retour-visible + flush ACK ciblé
Un terminal caché dans une grille de groupe (ou hors-écran) n'était pas repeint au retour — `visibilitychange` ne couvre que l'onglet — d'où l'écran noir avec curseur ; et son ACK ne progressait plus (callback xterm.write throttlé) → le serveur mettait le PTY en pause → sortie « par à-coups ». Ajoute un IntersectionObserver (repaint + flushAck ciblé au retour-visible) et expose Attachment.flushAck (factorisé avec flushAcks).
This commit is contained in:
@@ -38,6 +38,7 @@ const ended = ref(false);
|
||||
let term: Terminal | null = null;
|
||||
let attachment: Attachment | null = null;
|
||||
let resizeObserver: ResizeObserver | null = null;
|
||||
let intersectionObserver: IntersectionObserver | null = null;
|
||||
let onVisible: (() => void) | null = null;
|
||||
let disposed = false;
|
||||
|
||||
@@ -130,6 +131,20 @@ onMounted(async () => {
|
||||
activeTerm.onData((data) => attachment?.sendStdin(data));
|
||||
resizeObserver = new ResizeObserver(refit);
|
||||
resizeObserver.observe(container.value);
|
||||
// Re-révélation RÉELLE du conteneur : cellule de grille démontée/remontée (maximize↔grille), scroll
|
||||
// hors/dans le viewport, ou navigation SPA — autant de cas que `visibilitychange` (onglet only) ne
|
||||
// couvre PAS. Au retour visible, on repeint (le rendu était gelé hors-écran) ET on flushe l'ACK pour
|
||||
// sortir d'une éventuelle pause serveur (le callback de xterm.write était throttlé tant que caché).
|
||||
intersectionObserver = new IntersectionObserver((entries) => {
|
||||
for (const entry of entries) {
|
||||
if (!entry.isIntersecting) continue;
|
||||
// évite un fit() sur conteneur de taille 0 (remontage transitoire) → déforme le TUI
|
||||
if (entry.intersectionRect.width === 0 || entry.intersectionRect.height === 0) continue;
|
||||
refit();
|
||||
attachment?.flushAck();
|
||||
}
|
||||
});
|
||||
intersectionObserver.observe(container.value);
|
||||
// au retour en avant-plan, forcer un repaint (le renderer WebGL peut avoir « gelé » l'écran pendant
|
||||
// que l'onglet était caché) ; le ws-client flushe en parallèle les ACK pour relancer le flux.
|
||||
onVisible = (): void => {
|
||||
@@ -142,6 +157,7 @@ onMounted(async () => {
|
||||
onBeforeUnmount(() => {
|
||||
disposed = true;
|
||||
resizeObserver?.disconnect();
|
||||
intersectionObserver?.disconnect();
|
||||
if (onVisible) document.removeEventListener('visibilitychange', onVisible);
|
||||
attachment?.detach();
|
||||
term?.dispose();
|
||||
|
||||
Reference in New Issue
Block a user