<script lang="ts">
import { layoutStore } from '$lib/stores/layout.svelte.js';
import { appStore } from '$lib/store.svelte.js';
import { projectsStore } from '$lib/stores/projects.svelte.js';
import { sessionsStore } from '$lib/stores/sessions.svelte.js';
import ProjectList from '../sidebar/ProjectList.svelte';
import DirectoryBrowser from '../sidebar/DirectoryBrowser.svelte';
import SessionList from '../sidebar/SessionList.svelte';
let switching = $state(false);
function token(): string | undefined {
return appStore.authToken ?? undefined;
}
async function handleProjectSwitch(workingDir: string) {
if (switching) return;
switching = true;
try {
await projectsStore.switchTo(workingDir, token());
appStore.reset();
sessionsStore.clearSelection();
await sessionsStore.load(token());
} finally {
switching = false;
}
}
async function handleBrowseSelect(path: string) {
if (switching) return;
switching = true;
projectsStore.closeBrowser();
try {
await projectsStore.switchTo(path, token());
appStore.reset();
sessionsStore.clearSelection();
await sessionsStore.load(token());
} finally {
switching = false;
}
}
function handleNewSession() {
appStore.reset();
sessionsStore.clearSelection();
}
</script>
{#if layoutStore.leftSidebarOpen}
<aside class="left-sidebar">
<!-- Project header -->
<div class="section-header">
<span class="section-title">Projects</span>
<button
class="icon-btn"
onclick={() => projectsStore.openBrowser(token())}
aria-label="Add project"
title="Add project"
>+</button>
</div>
<!-- Directory browser (inline) -->
{#if projectsStore.browseMode}
<DirectoryBrowser
onselect={handleBrowseSelect}
onclose={() => projectsStore.closeBrowser()}
/>
{/if}
<!-- Project list -->
<div class="project-list-wrap">
<ProjectList onswitch={handleProjectSwitch} />
</div>
<!-- New Session -->
<div class="new-session-wrap">
<button class="new-session-btn" onclick={handleNewSession}>
+ New Session
</button>
</div>
<!-- Session list -->
<div class="session-list-wrap">
<SessionList />
</div>
<!-- Footer -->
<div class="sidebar-footer">
{#if appStore.serverVersion}
<span class="version">v{appStore.serverVersion}</span>
{/if}
</div>
</aside>
{/if}
<style>
.left-sidebar {
width: var(--left-w, 240px);
flex-shrink: 0;
background: var(--bg-surface);
border-right: 1px solid var(--border);
display: flex;
flex-direction: column;
overflow: hidden;
font-family: var(--font-mono);
}
.section-header {
display: flex;
align-items: center;
justify-content: space-between;
padding: 0.375rem 0.5rem;
border-bottom: 1px solid var(--border);
flex-shrink: 0;
}
.section-title {
font-size: 0.75rem;
font-weight: 700;
color: var(--fg-bright);
}
.icon-btn {
all: unset;
cursor: pointer;
color: var(--fg-dim);
width: 1.25rem;
height: 1.25rem;
display: flex;
align-items: center;
justify-content: center;
font-size: 0.875rem;
}
.icon-btn:hover {
color: var(--fg);
}
.project-list-wrap {
max-height: 160px;
overflow-y: auto;
border-bottom: 1px solid var(--border);
flex-shrink: 0;
}
.new-session-wrap {
padding: 0.375rem 0.5rem;
flex-shrink: 0;
}
.new-session-btn {
width: 100%;
padding: 0.25rem;
background: var(--bg-elevated);
border: 1px solid var(--border);
border-radius: 0;
color: var(--fg);
font-family: var(--font-mono);
font-size: 0.8125rem;
cursor: pointer;
text-align: center;
}
.new-session-btn:hover {
border-color: var(--accent-dim);
color: var(--fg-bright);
}
.session-list-wrap {
flex: 1;
overflow-y: auto;
}
.sidebar-footer {
padding: 0.25rem 0.5rem;
border-top: 1px solid var(--border);
flex-shrink: 0;
}
.version {
font-size: 0.6875rem;
color: var(--fg-dim);
}
</style>