优化folder打开逻辑

This commit is contained in:
xintaofei
2026-03-25 18:24:32 +08:00
parent b330a4f936
commit 388f92637c
9 changed files with 119 additions and 13 deletions

View File

@@ -345,7 +345,7 @@ export function BranchDropdown({
setWorktreeOpen(false)
await runGitTask(t("tasks.newWorktree", { name }), async () => {
await gitWorktreeAdd(folderPath, name, wtPath)
await openFolderWindow(wtPath)
await openFolderWindow(wtPath, { newWindow: true })
await setFolderParentBranch(wtPath, branch)
})
}

View File

@@ -54,13 +54,14 @@ export function FolderNameDropdown() {
if (selected) {
await openFolderWindow(
Array.isArray(selected) ? selected[0] : selected,
{ newWindow: true },
)
}
}
async function handleSelect(path: string) {
try {
await openFolderWindow(path)
await openFolderWindow(path, { newWindow: true })
} catch {
// ignore
}

View File

@@ -82,7 +82,7 @@ export function FolderTitleBar() {
const result = await openFileDialog({ directory: true, multiple: false })
if (!result) return
const selected = Array.isArray(result) ? result[0] : result
await openFolderWindow(selected)
await openFolderWindow(selected, { newWindow: true })
} catch (err) {
console.error("[FolderTitleBar] failed to open folder:", err)
}

View File

@@ -11,7 +11,8 @@ import {
type ReactNode,
} from "react"
import { toErrorMessage } from "@/lib/app-error"
import { getFolder, listFolderConversations } from "@/lib/api"
import { getFolder, listFolderConversations, closeFolderWindow } from "@/lib/api"
import { isDesktop } from "@/lib/transport"
import type {
AgentType,
AgentStats,
@@ -195,6 +196,22 @@ export function FolderProvider({
}
}, [])
// Web mode: register this tab's name so that window.open(url, "folder-{id}")
// from other pages can find and reuse it instead of opening duplicates.
// Also notify backend when the folder tab closes.
useEffect(() => {
if (isDesktop() || !folderId) return
window.name = `folder-${folderId}`
const onUnload = () => closeFolderWindow(folderId)
window.addEventListener("pagehide", onUnload)
return () => {
window.removeEventListener("pagehide", onUnload)
}
}, [folderId])
const selectConversation = useCallback((id: number, agentType: AgentType) => {
setSelectedConversation({ id, agentType })
setNewConversation(null)

View File

@@ -839,16 +839,23 @@ export async function gitAddFiles(
// Window management commands
export async function openFolderWindow(path: string): Promise<void> {
export async function openFolderWindow(
path: string,
options?: { newWindow?: boolean },
): Promise<void> {
if (getTransport().isDesktop()) {
return getTransport().call("open_folder_window", { path })
}
// Web mode: add folder to DB and navigate to folder page
const entry = await getTransport().call<{ id: number }>(
"open_folder_window",
{ path }
{ path },
)
window.location.href = `/folder?id=${entry.id}`
const url = `/folder?id=${entry.id}`
if (options?.newWindow) {
window.open(url, `folder-${entry.id}`)
} else {
window.location.href = url
}
}
export async function openCommitWindow(folderId: number): Promise<void> {
@@ -900,7 +907,25 @@ export async function listOpenFolders(): Promise<FolderHistoryEntry[]> {
}
export async function focusFolderWindow(folderId: number): Promise<void> {
return getTransport().call("focus_folder_window", { folderId })
if (getTransport().isDesktop()) {
return getTransport().call("focus_folder_window", { folderId })
}
// Web mode: use named window — reuses existing tab if still open,
// otherwise opens a new one.
window.open(`/folder?id=${folderId}`, `folder-${folderId}`)
}
/**
* Notify the backend that a folder tab has been closed.
* Uses sendBeacon for reliability during page unload.
*/
export function closeFolderWindow(folderId: number): void {
if (getTransport().isDesktop()) return
const token = localStorage.getItem("codeg_token") ?? ""
navigator.sendBeacon(
`/api/close_folder_window?token=${encodeURIComponent(token)}`,
JSON.stringify({ folderId }),
)
}
// Conversation CRUD commands