feat(web): infra IDE réutilisable (persisted-ref, splitter, bootstrap temps réel)
Extrait persistedRef dans lib/persisted-ref.ts (partagé, testable en node). Ajoute useSplitter + components/ide/PanelSplitter.vue (poignée de resize générique par pointer events, largeur/hauteur persistable), généralisant le resize souris de WorkspaceView. Hisse le chargement initial et les abonnements temps réel dans useRealtimeBootstrap (monté par App.vue) : un seul propriétaire actif sur TOUS les layouts, y compris la vue IDE plein écran. AppShell et WorkspaceView n'en portent plus la responsabilité. Tests unitaires persisted-ref et useSplitter (10).
This commit is contained in:
29
packages/web/src/components/ide/PanelSplitter.vue
Normal file
29
packages/web/src/components/ide/PanelSplitter.vue
Normal file
@@ -0,0 +1,29 @@
|
||||
<template>
|
||||
<div
|
||||
class="shrink-0 bg-transparent transition-colors hover:bg-accent/40"
|
||||
:class="axis === 'x' ? 'w-1 cursor-col-resize' : 'h-1 cursor-row-resize'"
|
||||
role="separator"
|
||||
:aria-orientation="axis === 'x' ? 'vertical' : 'horizontal'"
|
||||
@pointerdown="onPointerDown"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
// Poignée de redimensionnement réutilisable pour les panneaux de l'IDE.
|
||||
// La taille est un v-model (px) que le parent persiste via le store IDE.
|
||||
import { useSplitter } from '../../composables/useSplitter';
|
||||
|
||||
const size = defineModel<number>({ required: true });
|
||||
const props = defineProps<{ axis: 'x' | 'y'; min: number; max: number; invert?: boolean }>();
|
||||
|
||||
const { onPointerDown } = useSplitter({
|
||||
axis: props.axis,
|
||||
min: props.min,
|
||||
max: props.max,
|
||||
invert: props.invert,
|
||||
get: () => size.value,
|
||||
set: (v) => {
|
||||
size.value = v;
|
||||
},
|
||||
});
|
||||
</script>
|
||||
@@ -18,40 +18,11 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
// Coquille des vues authentifiées. Propriétaire unique du chargement initial et des abonnements
|
||||
// temps réel (sessions/worktrees/groups) pour toute la durée de la session : fiabilise le badge
|
||||
// de navigation, la palette ⌘K et la section « À traiter » quelle que soit la vue active.
|
||||
import { onMounted, onUnmounted } from 'vue';
|
||||
import { useSessionsStore } from '../../stores/sessions';
|
||||
import { useWorktreesStore } from '../../stores/worktrees';
|
||||
import { useGroupsStore } from '../../stores/groups';
|
||||
import { useSettingsStore } from '../../stores/settings';
|
||||
// Coquille des vues authentifiées (sidebar + contenu). Le chargement initial et les abonnements
|
||||
// temps réel sont désormais possédés par useRealtimeBootstrap (monté dans App.vue), pour couvrir
|
||||
// aussi la vue IDE plein écran qui n'utilise pas cette coquille.
|
||||
import AppSidebar from './AppSidebar.vue';
|
||||
import MobileTabBar from './MobileTabBar.vue';
|
||||
|
||||
defineProps<{ fullbleed?: boolean }>();
|
||||
|
||||
const sessions = useSessionsStore();
|
||||
const worktrees = useWorktreesStore();
|
||||
const groups = useGroupsStore();
|
||||
const settings = useSettingsStore();
|
||||
|
||||
onMounted(() => {
|
||||
void worktrees.fetchAll();
|
||||
void sessions.fetchSessions();
|
||||
void groups.fetchGroups();
|
||||
void settings.fetch(); // alimente l'icône de nav Gitea et la vue Réglages
|
||||
|
||||
worktrees.startRealtime();
|
||||
sessions.startRealtime();
|
||||
groups.startRealtime();
|
||||
settings.startRealtime(); // P11 : réglages synchronisés en temps réel (multi-onglets/clients)
|
||||
});
|
||||
|
||||
onUnmounted(() => {
|
||||
worktrees.stopRealtime();
|
||||
sessions.stopRealtime();
|
||||
groups.stopRealtime();
|
||||
settings.stopRealtime();
|
||||
});
|
||||
</script>
|
||||
|
||||
Reference in New Issue
Block a user