diff --git a/.reasonix/desktop-topic-titles.json b/.reasonix/desktop-topic-titles.json index cc4abdf..fe7cd63 100644 --- a/.reasonix/desktop-topic-titles.json +++ b/.reasonix/desktop-topic-titles.json @@ -37,5 +37,5 @@ "topic_20260707-092711_af706c3fcc7e435e": "帮我检查一下app.vue里的too…", "topic_20260707-095503_bf879b65e4666516": "帮我移除markdownEditor…", "topic_20260708-020616_9ab54d98daf65053": "帮我分析一下现在的markdownE…", - "topic_20260708-093419_71d1fea2e4b5a40f": "新的会话" + "topic_20260708-093419_71d1fea2e4b5a40f": "src/components/Dir…" } \ No newline at end of file diff --git a/src/components/DirectorySidebar.vue b/src/components/DirectorySidebar.vue index 548ef8f..2e6c8f8 100644 --- a/src/components/DirectorySidebar.vue +++ b/src/components/DirectorySidebar.vue @@ -67,17 +67,76 @@ const rootEntry = computed(() => { // ---- sidebar view mode ---- type ViewMode = "folder" | "search" | "setting"; const activeView = ref("folder"); -const expanded = ref(true); + +// ---- sidebar resize ---- +const MIN_SIDEBAR_WIDTH = 180; +const MAX_SIDEBAR_WIDTH = 500; +const COLLAPSED_WIDTH = 48; +const DEFAULT_EXPANDED_WIDTH = 288; + +const sidebarWidth = ref(DEFAULT_EXPANDED_WIDTH); +const lastExpandedWidth = ref(DEFAULT_EXPANDED_WIDTH); +const isResizing = ref(false); +const isCollapsed = computed(() => sidebarWidth.value <= COLLAPSED_WIDTH); + +function expand() { + sidebarWidth.value = lastExpandedWidth.value; +} + +function collapse() { + sidebarWidth.value = COLLAPSED_WIDTH; +} + +function toggleCollapse() { + if (isCollapsed.value) { + expand(); + } else { + collapse(); + } +} function switchView(view: ViewMode) { if (activeView.value === view) { - expanded.value = !expanded.value; + toggleCollapse(); } else { activeView.value = view; - expanded.value = true; + if (isCollapsed.value) { + expand(); + } } } +// ---- resize handle drag ---- +let resizeStartX = 0; +let resizeStartWidth = 0; + +function startResize(e: MouseEvent) { + resizeStartX = e.clientX; + resizeStartWidth = sidebarWidth.value; + isResizing.value = true; + document.addEventListener("mousemove", onResize); + document.addEventListener("mouseup", stopResize); + document.body.style.cursor = "col-resize"; + document.body.style.userSelect = "none"; + e.preventDefault(); +} + +function onResize(e: MouseEvent) { + if (!isResizing.value) return; + const delta = e.clientX - resizeStartX; + const newWidth = Math.min(MAX_SIDEBAR_WIDTH, Math.max(MIN_SIDEBAR_WIDTH, resizeStartWidth + delta)); + sidebarWidth.value = newWidth; + lastExpandedWidth.value = newWidth; +} + +function stopResize() { + isResizing.value = false; + document.removeEventListener("mousemove", onResize); + document.removeEventListener("mouseup", stopResize); + document.body.style.cursor = ""; + document.body.style.userSelect = ""; +} + // ---- workspace switcher ---- const workspaceSwitcherRef = ref(null); const showWorkspaceMenu = ref(false); @@ -240,6 +299,10 @@ watch(() => props.folderPath, () => { onBeforeUnmount(() => { document.removeEventListener("click", onDocumentClick); + document.removeEventListener("mousemove", onResize); + document.removeEventListener("mouseup", stopResize); + document.body.style.cursor = ""; + document.body.style.userSelect = ""; }); // ---- settings modal ---- @@ -259,7 +322,9 @@ function openSettings(page: SettingsPage) {