11'use client'
22
3- import { useMutation } from '@tanstack/react-query'
3+ import { useMutation , useQueryClient } from '@tanstack/react-query'
44import { useState } from 'react'
55import { toast } from 'sonner'
6+ import { useRouteParams } from '@/lib/hooks/use-route-params'
67import { useTRPC } from '@/trpc/client'
78import { AlertPopover } from '@/ui/alert-popover'
89import { Button } from '@/ui/primitives/button'
910import { PausedIcon } from '@/ui/primitives/icons'
10- import { useDashboard } from '../../context'
1111import { useSandboxContext } from '../context'
1212
1313interface PauseButtonProps {
@@ -17,28 +17,45 @@ interface PauseButtonProps {
1717export default function PauseButton ( { className } : PauseButtonProps ) {
1818 const [ open , setOpen ] = useState ( false )
1919 const { sandboxInfo, refetchSandboxInfo } = useSandboxContext ( )
20- const { team } = useDashboard ( )
20+ const { teamSlug, sandboxId } =
21+ useRouteParams < '/dashboard/[teamSlug]/sandboxes/[sandboxId]' > ( )
2122 const trpc = useTRPC ( )
23+ const queryClient = useQueryClient ( )
2224
2325 const canPause = sandboxInfo ?. state === 'running'
26+ const detailsKey = trpc . sandbox . details . queryKey ( { teamSlug, sandboxId } )
2427
2528 const { mutate : pause , isPending } = useMutation (
2629 trpc . sandbox . pause . mutationOptions ( {
30+ // Optimistically mark the sandbox as paused so the live terminal/filesystem
31+ // connections tear down immediately. Otherwise their envd traffic
32+ // auto-resumes the sandbox while the pause snapshot is being created.
33+ onMutate : async ( ) => {
34+ await queryClient . cancelQueries ( { queryKey : detailsKey } )
35+ const previous = queryClient . getQueryData ( detailsKey )
36+ queryClient . setQueryData ( detailsKey , ( old ) =>
37+ old ?. state === 'running' ? { ...old , state : 'paused' as const } : old
38+ )
39+ return { previous }
40+ } ,
41+ onError : ( _error , _variables , context ) => {
42+ if ( context ?. previous !== undefined ) {
43+ queryClient . setQueryData ( detailsKey , context . previous )
44+ }
45+ toast . error ( 'Failed to pause sandbox. Please try again.' )
46+ } ,
2747 onSuccess : async ( ) => {
2848 toast . success ( 'Sandbox paused successfully' )
2949 setOpen ( false )
3050 refetchSandboxInfo ( )
3151 } ,
32- onError : ( ) => {
33- toast . error ( 'Failed to pause sandbox. Please try again.' )
34- } ,
3552 } )
3653 )
3754
3855 const handlePause = ( ) => {
3956 if ( ! canPause || ! sandboxInfo ?. sandboxID ) return
4057
41- pause ( { teamSlug : team . slug , sandboxId : sandboxInfo . sandboxID } )
58+ pause ( { teamSlug, sandboxId : sandboxInfo . sandboxID } )
4259 }
4360
4461 if ( ! canPause ) return null
0 commit comments