feat: l'IDE devient la vue par défaut + deep-link worktree unifié
Some checks failed
CI / Build & test (Node 22) (push) Successful in 10m13s
CI / Pack & boot smoke (Node 22) (push) Has been cancelled
CI / No em/en dashes (push) Has been cancelled
CI / Build & test (Node 24) (push) Has been cancelled

Route / redirige vers /ide ; le dashboard passe à /dashboard (nom inchangé). /workspace/:repoId/:wt rend désormais l'IDE (IdeShell) : au montage il décode la clé, active et déplie le worktree ciblé, ouvre ?file= le cas échéant. WorkspaceView et useWorkspaceLayout retirés.

encode/decodeWtKey déplacés dans @arboretum/shared (source unique) avec décodeur TOLÉRANT (base64url OU chemin percent-encodé), corrigeant la divergence historique du deep-link VS Code. config.ts de l'extension aligné sur encodeWtKey. Tests wt-key (shared) + config (vscode) mis à jour. 431 tests.
This commit is contained in:
2026-07-17 17:28:48 +02:00
parent 6741b2d47c
commit d287c3c1d1
10 changed files with 97 additions and 262 deletions

View File

@@ -31,7 +31,9 @@
// Coquille de la vue IDE (layout 'ide', plein écran). Assemble barre d'activité, panneau gauche,
// zone centrale (éditeur), dock terminaux et barre de statut. Propriétaire de la réconciliation
// des ressources ouvertes contre les données live (worktrees / sessions).
import { watch } from 'vue';
import { onMounted, watch } from 'vue';
import { useRoute } from 'vue-router';
import { decodeWtKey } from '@arboretum/shared';
import { useIdeStore, wtKey } from '../../stores/ide';
import { useWorktreesStore } from '../../stores/worktrees';
import { useSessionsStore } from '../../stores/sessions';
@@ -45,6 +47,24 @@ import TerminalDock from './TerminalDock.vue';
const ide = useIdeStore();
const worktrees = useWorktreesStore();
const sessions = useSessionsStore();
const route = useRoute();
// Deep-link : /workspace/:repoId/:wt (ex. lien de l'extension VS Code) cible un worktree précis.
// On le rend actif, on déplie son sous-arbre, et on ouvre éventuellement ?file=<relPath>.
function applyDeepLink(): void {
if (route.name !== 'workspace') return;
const repoId = String(route.params.repoId ?? '');
const wt = decodeWtKey(String(route.params.wt ?? ''));
if (!repoId || !wt) return;
ide.setActivity('explorer');
ide.setActiveWorktree(repoId, wt);
if (!ide.expandedRepoIds.includes(repoId)) ide.toggleRepo(repoId);
if (!ide.expandedWtPaths.includes(wt)) ide.toggleWt(wt);
const file = route.query.file ? String(route.query.file) : null;
if (file) ide.openFile(repoId, wt, file);
}
onMounted(applyDeepLink);
watch(() => route.fullPath, applyDeepLink);
function prune(): void {
const live = new Set(sessions.sessions.filter((s) => s.live).map((s) => s.id));