11import type { Project , UserMessage , VcsFileDiff } from "@opencode-ai/sdk/v2"
22import { useDialog } from "@opencode-ai/ui/context/dialog"
3- import { useMutation } from "@tanstack/solid-query"
3+ import { createQuery , skipToken , useMutation , useQueryClient } from "@tanstack/solid-query"
44import {
55 batch ,
66 onCleanup ,
@@ -13,6 +13,8 @@ import {
1313 on ,
1414 onMount ,
1515 untrack ,
16+ Suspense ,
17+ startTransition ,
1618} from "solid-js"
1719import { makeEventListener } from "@solid-primitives/event-listener"
1820import { 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