feat(folder): unify workspace state streaming for tree and git panels

Introduce a shared workspace-state backend stream with snapshot/delta APIs for file tree and git changes.

Migrate both aux panels to a common frontend workspace store with lifecycle-safe stream handling.

Apply batched watch throttling, path-aware git refresh gating, no-op delta suppression, and bounded history compaction to improve runtime stability.
This commit is contained in:
xintaofei
2026-04-14 22:26:36 +08:00
parent 90e8bb645a
commit b5e8fd8acb
15 changed files with 2856 additions and 1419 deletions

View File

@@ -42,6 +42,7 @@ import type {
FilePreviewContent,
FileEditContent,
FileSaveResult,
WorkspaceSnapshotResponse,
GitLogResult,
SystemLanguageSettings,
SystemProxySettings,
@@ -1267,12 +1268,26 @@ export async function getFileTree(
})
}
export async function startFileTreeWatch(rootPath: string): Promise<void> {
return getTransport().call("start_file_tree_watch", { rootPath })
export async function startWorkspaceStateStream(
rootPath: string
): Promise<WorkspaceSnapshotResponse> {
return getTransport().call("start_workspace_state_stream", { rootPath })
}
export async function stopFileTreeWatch(rootPath: string): Promise<void> {
return getTransport().call("stop_file_tree_watch", { rootPath })
export async function stopWorkspaceStateStream(
rootPath: string
): Promise<void> {
return getTransport().call("stop_workspace_state_stream", { rootPath })
}
export async function getWorkspaceSnapshot(
rootPath: string,
sinceSeq?: number
): Promise<WorkspaceSnapshotResponse> {
return getTransport().call("get_workspace_snapshot", {
rootPath,
sinceSeq: sinceSeq ?? null,
})
}
export async function readFileBase64(

View File

@@ -40,6 +40,7 @@ import type {
FilePreviewContent,
FileEditContent,
FileSaveResult,
WorkspaceSnapshotResponse,
GitLogResult,
SystemLanguageSettings,
SystemProxySettings,
@@ -1010,12 +1011,26 @@ export async function getFileTree(
return invoke("get_file_tree", { path, maxDepth: maxDepth ?? null })
}
export async function startFileTreeWatch(rootPath: string): Promise<void> {
return invoke("start_file_tree_watch", { rootPath })
export async function startWorkspaceStateStream(
rootPath: string
): Promise<WorkspaceSnapshotResponse> {
return invoke("start_workspace_state_stream", { rootPath })
}
export async function stopFileTreeWatch(rootPath: string): Promise<void> {
return invoke("stop_file_tree_watch", { rootPath })
export async function stopWorkspaceStateStream(
rootPath: string
): Promise<void> {
return invoke("stop_workspace_state_stream", { rootPath })
}
export async function getWorkspaceSnapshot(
rootPath: string,
sinceSeq?: number
): Promise<WorkspaceSnapshotResponse> {
return invoke("get_workspace_snapshot", {
rootPath,
sinceSeq: sinceSeq ?? null,
})
}
export async function readFileBase64(

View File

@@ -831,12 +831,42 @@ export interface FileSaveResult {
line_ending: "lf" | "crlf" | "mixed" | "none"
}
export interface FileTreeChangedEvent {
export interface WorkspaceGitEntry {
path: string
status: string
additions: number
deletions: number
}
export type WorkspaceDelta =
| { kind: "tree_replace"; nodes: FileTreeNode[] }
| { kind: "git_replace"; entries: WorkspaceGitEntry[] }
| { kind: "meta"; reason: string }
export interface WorkspaceDeltaEnvelope {
seq: number
kind: "fs_delta" | "git_delta" | "meta" | "resync_hint" | string
payload: WorkspaceDelta[]
requires_resync: boolean
}
export interface WorkspaceStateEvent {
root_path: string
changed_paths: string[]
kind: "create" | "modify" | "remove" | "access" | "any" | "other"
full_reload: boolean
refresh_git_status: boolean
seq: number
version: number
kind: "fs_delta" | "git_delta" | "meta" | "resync_hint" | string
payload: WorkspaceDelta[]
requires_resync: boolean
}
export interface WorkspaceSnapshotResponse {
root_path: string
seq: number
version: number
full: boolean
tree_snapshot: FileTreeNode[] | null
git_snapshot: WorkspaceGitEntry[] | null
deltas: WorkspaceDeltaEnvelope[]
}
export interface GitLogResult {