fix(desktop): handle moved projects and deleted paths

This commit is contained in:
𝓛𝓲𝓽𝓽𝓵𝓮 𝓕𝓻𝓪𝓷𝓴 2026-06-27 02:14:03 +00:00
commit c9e1aedd42
6 changed files with 176 additions and 9 deletions

View file

@ -40,6 +40,7 @@ beforeAll(async () => {
describe("file tree fetch discipline", () => {
test("root lists on mount unless already loaded or loading", () => {
expect(shouldListRoot({ level: 0 })).toBe(true)
expect(shouldListRoot({ level: 0, filtered: true })).toBe(false)
expect(shouldListRoot({ level: 0, dir: { loaded: true } })).toBe(false)
expect(shouldListRoot({ level: 0, dir: { loading: true } })).toBe(false)
expect(shouldListRoot({ level: 1 })).toBe(false)

View file

@ -32,7 +32,12 @@ type Filter = {
dirs: Set<string>
}
export function shouldListRoot(input: { level: number; dir?: { loaded?: boolean; loading?: boolean } }) {
export function shouldListRoot(input: {
level: number
filtered?: boolean
dir?: { loaded?: boolean; loading?: boolean }
}) {
if (input.filtered) return false
if (input.level !== 0) return false
if (input.dir?.loaded) return false
if (input.dir?.loading) return false
@ -309,7 +314,7 @@ export default function FileTree(props: {
filter: current,
expanded: (dir) => untrack(() => file.tree.state(dir)?.expanded) ?? false,
})
for (const dir of dirs) file.tree.expand(dir)
for (const dir of dirs) file.tree.expand(dir, { load: false })
})
createEffect(
@ -317,7 +322,7 @@ export default function FileTree(props: {
() => props.path,
(path) => {
const dir = untrack(() => file.tree.state(path))
if (!shouldListRoot({ level, dir })) return
if (!shouldListRoot({ level, filtered: !!filter(), dir })) return
void file.tree.list(path)
},
{ defer: false },
@ -401,7 +406,9 @@ export default function FileTree(props: {
data-scope="filetree"
forceMount={false}
open={expanded()}
onOpenChange={(open) => (open ? file.tree.expand(node.path) : file.tree.collapse(node.path))}
onOpenChange={(open) =>
open ? file.tree.expand(node.path, { load: !filter() }) : file.tree.collapse(node.path)
}
>
<Collapsible.Trigger>
<FileTreeNode

View file

@ -0,0 +1,28 @@
import { describe, expect, test } from "bun:test"
import { createRoot } from "solid-js"
import { createFileTreeStore } from "./tree-store"
describe("file tree store", () => {
test("expands synthetic directories without listing them", () => {
const listed: string[] = []
const value = createRoot((dispose) => ({
dispose,
tree: createFileTreeStore({
scope: () => "/project",
normalizeDir: (input) => input,
list: (input) => {
listed.push(input)
return Promise.resolve([])
},
onError: () => undefined,
}),
}))
value.tree.expandDir("deleted/parent", { load: false })
expect(value.tree.dirState("deleted/parent")?.expanded).toBe(true)
expect(listed).toEqual([])
value.dispose()
})
})

View file

@ -127,10 +127,11 @@ export function createFileTreeStore(options: TreeStoreOptions) {
return promise
}
const expandDir = (input: string) => {
const expandDir = (input: string, opts?: { load?: boolean }) => {
const dir = options.normalizeDir(input)
ensureDir(dir)
setTree("dir", dir, "expanded", true)
if (opts?.load === false) return
void listDir(dir)
}