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:
2026-06-23 17:42:49 +02:00
parent 5ebe3a0f37
commit 663ae7ace1
15 changed files with 192 additions and 30 deletions

View File

@@ -16,7 +16,7 @@
<div class="mt-1 flex flex-wrap items-center gap-2">
<RouterLink
v-for="s in worktree.sessions"
v-for="s in visibleSessions"
:key="s.id"
:to="{ name: 'session', params: { id: s.id } }"
class="flex items-center gap-1 rounded bg-zinc-800/60 px-1.5 py-0.5 transition-colors hover:bg-zinc-800"
@@ -24,7 +24,16 @@
<SessionStateBadge :session="liveSession(s)" />
<span class="font-mono text-[11px] text-zinc-400">{{ s.command }}</span>
</RouterLink>
<span v-if="worktree.sessions.length === 0" class="text-xs text-zinc-600">{{ t('worktrees.noSession') }}</span>
<!-- sessions externes (lancées hors Arboretum) masquées par défaut : chip de révélation -->
<button
v-if="!store.showExternalSessions && externalCount > 0"
type="button"
class="rounded bg-zinc-800/40 px-1.5 py-0.5 text-[11px] text-zinc-500 transition-colors hover:text-zinc-300"
@click="store.showExternalSessions = true"
>
+{{ externalCount }} {{ t('worktrees.externalSessions') }}
</button>
<span v-if="visibleSessions.length === 0 && externalCount === 0" class="text-xs text-zinc-600">{{ t('worktrees.noSession') }}</span>
<!-- lancement d'une session sur ce worktree ; carte principale = bosser sur la branche principale -->
<button v-if="hasLiveSession && !showLauncher" class="btn text-xs" @click="showLauncher = true">+ {{ t('worktrees.start') }}</button>
@@ -123,6 +132,17 @@ function liveSession(s: SessionSummary): SessionSummary {
return sessions.sessions.find((x) => x.id === s.id) ?? s;
}
// sessions « liées à l'app » (managées) affichées par défaut ; les externes (découvertes hors
// Arboretum) ne le sont que si l'interrupteur global est activé → évite les listes à rallonge.
const visibleSessions = computed(() =>
store.showExternalSessions
? props.worktree.sessions
: props.worktree.sessions.filter((s) => liveSession(s).source === 'managed'),
);
const externalCount = computed(
() => props.worktree.sessions.filter((s) => liveSession(s).source !== 'managed').length,
);
// sessions corrélées actuellement bloquées sur un dialogue → réponse rapide inline.
const waitingSessions = computed(() =>
props.worktree.sessions.map(liveSession).filter((s) => s.live && s.activity === 'waiting' && s.dialog),