- 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.
65 lines
2.6 KiB
Vue
65 lines
2.6 KiB
Vue
<template>
|
|
<div class="flex flex-col gap-2">
|
|
<p v-if="sessions.length === 0" class="text-sm text-zinc-500">{{ t('groups.gridEmpty') }}</p>
|
|
<template v-else>
|
|
<p v-if="!activeMax && sessions.length > MAX_CELLS" class="text-xs text-amber-400">
|
|
{{ t('groups.gridCapped', { shown: MAX_CELLS, total: sessions.length }) }}
|
|
</p>
|
|
<!-- une seule socket WS multiplexe tous les terminaux ; cap dur pour préserver GPU/canaux.
|
|
Sur mobile la grille retombe à une colonne (empilement). Hauteur relative au viewport
|
|
(dvh) : terminaux grands sur PC, exploitables sur mobile ; xterm re-fit via ResizeObserver.
|
|
Plancher min-h-80 pour les fenêtres courtes. -->
|
|
<!-- une cellule maximisée → plein cadre ; sinon la grille responsive -->
|
|
<div v-if="activeMax" class="grid grid-cols-1">
|
|
<TerminalCell
|
|
:session="activeMax"
|
|
maximized
|
|
class="h-[calc(100dvh-8rem)] min-h-80"
|
|
@toggle-maximize="toggleMax(activeMax.id)"
|
|
@open-fullscreen="openFullscreen(activeMax.id)"
|
|
/>
|
|
</div>
|
|
<div v-else class="grid grid-cols-1 gap-3 lg:grid-cols-2 2xl:grid-cols-3">
|
|
<TerminalCell
|
|
v-for="s in shown"
|
|
:key="s.id"
|
|
:session="s"
|
|
class="h-[68dvh] min-h-80 lg:h-[calc((100dvh-9rem)/2)]"
|
|
@toggle-maximize="toggleMax(s.id)"
|
|
@open-fullscreen="openFullscreen(s.id)"
|
|
/>
|
|
</div>
|
|
</template>
|
|
</div>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
import { computed, ref } from 'vue';
|
|
import { useI18n } from 'vue-i18n';
|
|
import { useRouter } from 'vue-router';
|
|
import type { SessionSummary } from '@arboretum/shared';
|
|
import TerminalCell from './TerminalCell.vue';
|
|
|
|
const props = defineProps<{ sessions: SessionSummary[] }>();
|
|
const { t } = useI18n();
|
|
const router = useRouter();
|
|
|
|
const MAX_CELLS = 6;
|
|
const shown = computed(() => props.sessions.slice(0, MAX_CELLS));
|
|
|
|
// ouvrir le terminal choisi en plein écran (page dédiée /sessions/:id), comme depuis la liste des sessions.
|
|
function openFullscreen(id: string): void {
|
|
void router.push({ name: 'session', params: { id } });
|
|
}
|
|
|
|
// Maximisation d'une cellule au choix (état purement présentation, local à la grille). Si la session
|
|
// maximisée disparaît (terminée), on retombe automatiquement sur la grille.
|
|
const maximizedId = ref<string | null>(null);
|
|
function toggleMax(id: string): void {
|
|
maximizedId.value = maximizedId.value === id ? null : id;
|
|
}
|
|
const activeMax = computed<SessionSummary | null>(() =>
|
|
maximizedId.value ? (shown.value.find((s) => s.id === maximizedId.value) ?? null) : null,
|
|
);
|
|
</script>
|