Skip to content

Commit 292f97e

Browse files
Apply PR #22277: app: use tanstack query to load session vcs state
2 parents 1cf607a + 48a5d5c commit 292f97e

1 file changed

Lines changed: 46 additions & 132 deletions

File tree

packages/app/src/pages/session.tsx

Lines changed: 46 additions & 132 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import type { Project, UserMessage, VcsFileDiff } from "@opencode-ai/sdk/v2"
22
import { useDialog } from "@opencode-ai/ui/context/dialog"
3-
import { useMutation } from "@tanstack/solid-query"
3+
import { createQuery, skipToken, useMutation, useQueryClient } from "@tanstack/solid-query"
44
import {
55
batch,
66
onCleanup,
@@ -13,6 +13,8 @@ import {
1313
on,
1414
onMount,
1515
untrack,
16+
Suspense,
17+
startTransition,
1618
} from "solid-js"
1719
import { makeEventListener } from "@solid-primitives/event-listener"
1820
import { createMediaQuery } from "@solid-primitives/media"
@@ -323,6 +325,7 @@ export default function Page() {
323325
const local = useLocal()
324326
const file = useFile()
325327
const sync = useSync()
328+
const queryClient = useQueryClient()
326329
const dialog = useDialog()
327330
const language = useLanguage()
328331
const sdk = useSDK()
@@ -521,26 +524,6 @@ export default function Page() {
521524
deferRender: false,
522525
})
523526

524-
const [vcs, setVcs] = createStore<{
525-
diff: {
526-
git: VcsFileDiff[]
527-
branch: VcsFileDiff[]
528-
}
529-
ready: {
530-
git: boolean
531-
branch: boolean
532-
}
533-
}>({
534-
diff: {
535-
git: [] as VcsFileDiff[],
536-
branch: [] as VcsFileDiff[],
537-
},
538-
ready: {
539-
git: false,
540-
branch: false,
541-
},
542-
})
543-
544527
const [followup, setFollowup] = persisted(
545528
Persist.workspace(sdk.directory, "followup", ["followup.v1"]),
546529
createStore<{
@@ -574,68 +557,6 @@ export default function Page() {
574557
let todoTimer: number | undefined
575558
let diffFrame: number | undefined
576559
let diffTimer: number | undefined
577-
const vcsTask = new Map<VcsMode, Promise<void>>()
578-
const vcsRun = new Map<VcsMode, number>()
579-
580-
const bumpVcs = (mode: VcsMode) => {
581-
const next = (vcsRun.get(mode) ?? 0) + 1
582-
vcsRun.set(mode, next)
583-
return next
584-
}
585-
586-
const resetVcs = (mode?: VcsMode) => {
587-
const list = mode ? [mode] : (["git", "branch"] as const)
588-
list.forEach((item) => {
589-
bumpVcs(item)
590-
vcsTask.delete(item)
591-
setVcs("diff", item, [])
592-
setVcs("ready", item, false)
593-
})
594-
}
595-
596-
const loadVcs = (mode: VcsMode, force = false) => {
597-
if (sync.project?.vcs !== "git") return Promise.resolve()
598-
if (!force && vcs.ready[mode]) return Promise.resolve()
599-
600-
if (force) {
601-
if (vcsTask.has(mode)) bumpVcs(mode)
602-
vcsTask.delete(mode)
603-
setVcs("ready", mode, false)
604-
}
605-
606-
const current = vcsTask.get(mode)
607-
if (current) return current
608-
609-
const run = bumpVcs(mode)
610-
611-
const task = sdk.client.vcs
612-
.diff({ mode })
613-
.then((result) => {
614-
if (vcsRun.get(mode) !== run) return
615-
setVcs("diff", mode, list(result.data))
616-
setVcs("ready", mode, true)
617-
})
618-
.catch((error) => {
619-
if (vcsRun.get(mode) !== run) return
620-
console.debug("[session-review] failed to load vcs diff", { mode, error })
621-
setVcs("diff", mode, [])
622-
setVcs("ready", mode, true)
623-
})
624-
.finally(() => {
625-
if (vcsTask.get(mode) === task) vcsTask.delete(mode)
626-
})
627-
628-
vcsTask.set(mode, task)
629-
return task
630-
}
631-
632-
const refreshVcs = () => {
633-
resetVcs()
634-
const mode = untrack(vcsMode)
635-
if (!mode) return
636-
if (!untrack(wantsReview)) return
637-
void loadVcs(mode, true)
638-
}
639560

640561
createComputed((prev) => {
641562
const open = desktopReviewOpen()
@@ -666,21 +587,52 @@ export default function Page() {
666587
list.push("turn")
667588
return list
668589
})
590+
const mobileChanges = createMemo(() => !isDesktop() && store.mobileTab === "changes")
591+
const wantsReview = createMemo(() =>
592+
isDesktop()
593+
? desktopFileTreeOpen() || (desktopReviewOpen() && activeTab() === "review")
594+
: store.mobileTab === "changes",
595+
)
669596
const vcsMode = createMemo<VcsMode | undefined>(() => {
670597
if (store.changes === "git" || store.changes === "branch") return store.changes
671598
})
672-
const reviewDiffs = createMemo(() => {
673-
if (store.changes === "git") return list(vcs.diff.git)
674-
if (store.changes === "branch") return list(vcs.diff.branch)
675-
return turnDiffs()
599+
const vcsKey = createMemo(
600+
() => ["session-vcs", sdk.directory, sync.data.vcs?.branch ?? "", sync.data.vcs?.default_branch ?? ""] as const,
601+
)
602+
const vcsQuery = createQuery(() => {
603+
const mode = vcsMode()
604+
const enabled = wantsReview() && sync.project?.vcs === "git"
605+
606+
return {
607+
queryKey: [...vcsKey(), mode] as const,
608+
enabled,
609+
staleTime: Number.POSITIVE_INFINITY,
610+
gcTime: 60 * 1000,
611+
queryFn: mode
612+
? () =>
613+
sdk.client.vcs
614+
.diff({ mode })
615+
.then((result) => list(result.data))
616+
.catch((error) => {
617+
console.debug("[session-review] failed to load vcs diff", { mode, error })
618+
return []
619+
})
620+
: skipToken,
621+
}
676622
})
677-
const reviewCount = createMemo(() => reviewDiffs().length)
678-
const hasReview = createMemo(() => reviewCount() > 0)
679-
const reviewReady = createMemo(() => {
680-
if (store.changes === "git") return vcs.ready.git
681-
if (store.changes === "branch") return vcs.ready.branch
623+
const refreshVcs = () => void queryClient.invalidateQueries({ queryKey: vcsKey() })
624+
const reviewDiffs = () => {
625+
if (store.changes === "git" || store.changes === "branch")
626+
// avoids suspense
627+
return vcsQuery.isFetched ? (vcsQuery.data ?? []) : []
628+
return turnDiffs()
629+
}
630+
const reviewCount = () => reviewDiffs().length
631+
const hasReview = () => reviewCount() > 0
632+
const reviewReady = () => {
633+
if (store.changes === "git" || store.changes === "branch") return !vcsQuery.isPending
682634
return true
683-
})
635+
}
684636

685637
const newSessionWorktree = createMemo(() => {
686638
if (store.newSessionWorktree === "create") return "create"
@@ -900,27 +852,6 @@ export default function Page() {
900852
),
901853
)
902854

903-
createEffect(
904-
on(
905-
() => sdk.directory,
906-
() => {
907-
resetVcs()
908-
},
909-
{ defer: true },
910-
),
911-
)
912-
913-
createEffect(
914-
on(
915-
() => [sync.data.vcs?.branch, sync.data.vcs?.default_branch] as const,
916-
(next, prev) => {
917-
if (prev === undefined || same(next, prev)) return
918-
refreshVcs()
919-
},
920-
{ defer: true },
921-
),
922-
)
923-
924855
const stopVcs = sdk.event.listen((evt) => {
925856
if (evt.details.type !== "file.watcher.updated") return
926857
const props =
@@ -1054,13 +985,6 @@ export default function Page() {
1054985
}
1055986
}
1056987

1057-
const mobileChanges = createMemo(() => !isDesktop() && store.mobileTab === "changes")
1058-
const wantsReview = createMemo(() =>
1059-
isDesktop()
1060-
? desktopFileTreeOpen() || (desktopReviewOpen() && activeTab() === "review")
1061-
: store.mobileTab === "changes",
1062-
)
1063-
1064988
createEffect(() => {
1065989
const list = changesOptions()
1066990
if (list.includes(store.changes)) return
@@ -1069,22 +993,12 @@ export default function Page() {
1069993
setStore("changes", next)
1070994
})
1071995

1072-
createEffect(() => {
1073-
const mode = vcsMode()
1074-
if (!mode) return
1075-
if (!wantsReview()) return
1076-
void loadVcs(mode)
1077-
})
1078-
1079996
createEffect(
1080997
on(
1081998
() => sync.data.session_status[params.id ?? ""]?.type,
1082999
(next, prev) => {
1083-
const mode = vcsMode()
1084-
if (!mode) return
1085-
if (!wantsReview()) return
10861000
if (next !== "idle" || prev === undefined || prev === "idle") return
1087-
void loadVcs(mode, true)
1001+
refreshVcs()
10881002
},
10891003
{ defer: true },
10901004
),

0 commit comments

Comments
 (0)