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

@@ -1,4 +1,4 @@
import { computed, ref } from 'vue';
import { computed, effectScope, ref } from 'vue';
import type { WorktreeSummary } from '@arboretum/shared';
import type { ListToolbarControls, SortDir } from './useListControls';
import { useDebouncedRef } from './useDebouncedRef';
@@ -29,7 +29,14 @@ function create(): WorktreeView {
const filterDefList = worktreeFilters();
const filterDefs = computed(() => filterDefList);
const accessor = (w: WorktreeSummary): string => `${w.branch ?? ''} ${w.path}`.toLowerCase();
// label de repo cherchable (en plus de la branche et du chemin) → la recherche couvre le nom du dépôt.
const repoLabelById = computed(() => {
const m = new Map<string, string>();
for (const r of useWorktreesStore().repos) m.set(r.id, r.label);
return m;
});
const accessor = (w: WorktreeSummary): string =>
`${repoLabelById.value.get(w.repoId) ?? ''} ${w.branch ?? ''} ${w.path}`.toLowerCase();
function apply(list: readonly WorktreeSummary[]): WorktreeSummary[] {
let items = [...list];
@@ -98,6 +105,12 @@ function create(): WorktreeView {
}
export function useWorktreeView(): WorktreeView {
instance ??= create();
// Effets (watch du debounce, computeds) créés dans un scope DÉTACHÉ : sinon ils seraient rattachés
// au scope du premier composant qui appelle ce singleton et stoppés à son démontage (navigation),
// gelant le ref débouncé → la recherche ne filtrerait plus après un aller-retour de route.
if (!instance) {
const scope = effectScope(true);
instance = scope.run(() => create())!;
}
return instance;
}