fix: recherche worktrees, sessions externes masquées, rendu/historique terminal & plein écran grille
- Recherche : le watcher débouncé du singleton useWorktreeView est créé dans un effectScope détaché → ne gèle plus après une navigation ; recherche aussi par label de dépôt ; accès à la palette depuis le MoreSheet mobile (sidebar/⌘K indisponibles sur mobile). - Sessions : sessionsForCwd exclut désormais toujours les sessions masquées ; les sessions externes (discovered) sont masquées par défaut côté UI, avec puce de révélation par carte et case globale dans le dashboard. - Terminal : ACK découplé du callback de rendu (armé à la réception + flush au retour de visibilité) → plus de pause PTY quand l'onglet passe en arrière-plan ; repaint forcé sur perte de contexte WebGL / resize / retour en avant-plan. Historique élargi : REPLAY_TAIL_BYTES 1 Mo, RING_CAPACITY 4 Mo, scrollback xterm 20k. - Grille de groupe : bouton « plein écran » sur chaque cellule ouvrant /sessions/:id.
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 onVisible: (() => void) | null = null;
|
||||
let disposed = false;
|
||||
|
||||
onMounted(async () => {
|
||||
@@ -47,7 +48,7 @@ onMounted(async () => {
|
||||
cursorBlink: true,
|
||||
fontSize: 13,
|
||||
fontFamily: "ui-monospace, 'JetBrains Mono', 'Fira Code', Menlo, Consolas, monospace",
|
||||
scrollback: 10_000,
|
||||
scrollback: 20_000, // absorbe le replay élargi (REPLAY_TAIL_BYTES = 1 Mo) → on remonte plus loin
|
||||
theme: {
|
||||
background: '#09090b',
|
||||
foreground: '#d4d4d8',
|
||||
@@ -58,18 +59,24 @@ onMounted(async () => {
|
||||
const fit = new FitAddon();
|
||||
term.loadAddon(fit);
|
||||
term.open(container.value);
|
||||
const activeTerm = term;
|
||||
|
||||
try {
|
||||
const { WebglAddon } = await import('@xterm/addon-webgl');
|
||||
const webgl = new WebglAddon();
|
||||
webgl.onContextLoss(() => webgl.dispose());
|
||||
// perte de contexte GPU : on dispose (retour au renderer DOM) PUIS on repeint — sinon l'écran
|
||||
// reste figé sur le dernier rendu WebGL jusqu'à la prochaine interaction (« texte qui ne s'affiche
|
||||
// que si ça bouge »).
|
||||
webgl.onContextLoss(() => {
|
||||
webgl.dispose();
|
||||
activeTerm.refresh(0, activeTerm.rows - 1);
|
||||
});
|
||||
term.loadAddon(webgl);
|
||||
} catch {
|
||||
// WebGL indisponible : xterm retombe sur le renderer DOM
|
||||
}
|
||||
|
||||
fit.fit();
|
||||
const activeTerm = term;
|
||||
|
||||
// Re-mesure après stabilisation du layout flex : au `onMounted`, le conteneur peut ne pas avoir sa
|
||||
// taille finale (la hauteur flex se résout après le 1er paint) → un seul `fit()` donne trop peu de
|
||||
@@ -82,6 +89,9 @@ onMounted(async () => {
|
||||
/* conteneur sans dimension (démontage en cours) : ignoré */
|
||||
}
|
||||
attachment?.resize(activeTerm.cols, activeTerm.rows);
|
||||
// repaint explicite : le renderer WebGL ne repeint pas toujours une zone non « dirty » (retour
|
||||
// d'arrière-plan, resync) → on force un rafraîchissement pour éviter un écran figé.
|
||||
activeTerm.refresh(0, activeTerm.rows - 1);
|
||||
};
|
||||
|
||||
try {
|
||||
@@ -120,12 +130,19 @@ onMounted(async () => {
|
||||
activeTerm.onData((data) => attachment?.sendStdin(data));
|
||||
resizeObserver = new ResizeObserver(refit);
|
||||
resizeObserver.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 => {
|
||||
if (document.visibilityState === 'visible') activeTerm.refresh(0, activeTerm.rows - 1);
|
||||
};
|
||||
document.addEventListener('visibilitychange', onVisible);
|
||||
if (props.mode === 'interactive') activeTerm.focus();
|
||||
});
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
disposed = true;
|
||||
resizeObserver?.disconnect();
|
||||
if (onVisible) document.removeEventListener('visibilitychange', onVisible);
|
||||
attachment?.detach();
|
||||
term?.dispose();
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user