11import { useState , useEffect , useCallback } from "react"
2- import { DotsHorizontalIcon } from "@radix-ui/react-icons"
3- import { DropdownMenuItemProps } from "@radix-ui/react-dropdown-menu"
2+ import { CheckIcon , Cross2Icon } from "@radix-ui/react-icons"
43
54import { vscode } from "../../../utils/vscode"
65
7- import {
8- Button ,
9- DropdownMenu ,
10- DropdownMenuTrigger ,
11- DropdownMenuContent ,
12- DropdownMenuItem ,
13- DropdownMenuShortcut ,
14- } from "@/components/ui"
6+ import { Button , Popover , PopoverContent , PopoverTrigger } from "@/components/ui"
157
168type CheckpointMenuProps = {
179 ts : number
1810 commitHash : string
11+ currentCheckpointHash ?: string
1912}
2013
21- export const CheckpointMenu = ( { ts, commitHash } : CheckpointMenuProps ) => {
14+ export const CheckpointMenu = ( { ts, commitHash, currentCheckpointHash } : CheckpointMenuProps ) => {
2215 const [ portalContainer , setPortalContainer ] = useState < HTMLElement > ( )
16+ const [ isOpen , setIsOpen ] = useState ( false )
17+ const [ isConfirming , setIsConfirming ] = useState ( false )
2318
24- const onTaskDiff = useCallback ( ( ) => {
25- vscode . postMessage ( { type : "checkpointDiff" , payload : { ts, commitHash, mode : "full" } } )
26- } , [ ts , commitHash ] )
19+ const isCurrent = currentCheckpointHash === commitHash
2720
2821 const onCheckpointDiff = useCallback ( ( ) => {
2922 vscode . postMessage ( { type : "checkpointDiff" , payload : { ts, commitHash, mode : "checkpoint" } } )
3023 } , [ ts , commitHash ] )
3124
3225 const onPreview = useCallback ( ( ) => {
3326 vscode . postMessage ( { type : "checkpointRestore" , payload : { ts, commitHash, mode : "preview" } } )
27+ setIsOpen ( false )
3428 } , [ ts , commitHash ] )
3529
3630 const onRestore = useCallback ( ( ) => {
3731 vscode . postMessage ( { type : "checkpointRestore" , payload : { ts, commitHash, mode : "restore" } } )
32+ setIsOpen ( false )
3833 } , [ ts , commitHash ] )
3934
4035 useEffect ( ( ) => {
@@ -47,34 +42,68 @@ export const CheckpointMenu = ({ ts, commitHash }: CheckpointMenuProps) => {
4742 } , [ ] )
4843
4944 return (
50- < DropdownMenu >
51- < DropdownMenuTrigger asChild >
52- < Button variant = "ghost" size = "icon" >
53- < DotsHorizontalIcon />
54- </ Button >
55- </ DropdownMenuTrigger >
56- < DropdownMenuContent container = { portalContainer } align = "end" >
57- < CheckpointMenuItem label = "Checkpoint Diff" icon = "diff-single" onClick = { onCheckpointDiff } />
58- < CheckpointMenuItem label = "Task Diff" icon = "diff-multiple" onClick = { onTaskDiff } />
59- < CheckpointMenuItem label = "Preview" icon = "open-preview" onClick = { onPreview } />
60- < CheckpointMenuItem label = "Restore" icon = "history" onClick = { onRestore } />
61- </ DropdownMenuContent >
62- </ DropdownMenu >
45+ < div className = "flex flex-row gap-1" >
46+ < Button variant = "ghost" size = "icon" onClick = { onCheckpointDiff } >
47+ < span className = "codicon codicon-diff-single" />
48+ </ Button >
49+ < Popover
50+ open = { isOpen }
51+ onOpenChange = { ( open ) => {
52+ setIsOpen ( open )
53+ setIsConfirming ( false )
54+ } } >
55+ < PopoverTrigger asChild >
56+ < Button variant = "ghost" size = "icon" >
57+ < span className = "codicon codicon-history" />
58+ </ Button >
59+ </ PopoverTrigger >
60+ < PopoverContent align = "end" container = { portalContainer } >
61+ < div className = "flex flex-col gap-2" >
62+ { ! isCurrent && (
63+ < div className = "flex flex-col gap-1 group hover:text-foreground" >
64+ < Button variant = "secondary" onClick = { onPreview } >
65+ Restore Files
66+ </ Button >
67+ < div className = "text-muted transition-colors group-hover:text-foreground" >
68+ Restores your project's files back to a snapshot taken at this point.
69+ </ div >
70+ </ div >
71+ ) }
72+ < div className = "flex flex-col gap-1 group hover:text-foreground" >
73+ < div className = "flex flex-col gap-1 group hover:text-foreground" >
74+ { ! isConfirming ? (
75+ < Button variant = "secondary" onClick = { ( ) => setIsConfirming ( true ) } >
76+ Restore Files & Task
77+ </ Button >
78+ ) : (
79+ < >
80+ < Button variant = "default" onClick = { onRestore } className = "grow" >
81+ < div className = "flex flex-row gap-1" >
82+ < CheckIcon />
83+ < div > Confirm</ div >
84+ </ div >
85+ </ Button >
86+ < Button variant = "secondary" onClick = { ( ) => setIsConfirming ( false ) } >
87+ < div className = "flex flex-row gap-1" >
88+ < Cross2Icon />
89+ < div > Cancel</ div >
90+ </ div >
91+ </ Button >
92+ </ >
93+ ) }
94+ { isConfirming ? (
95+ < div className = "text-destructive font-bold" > This action cannot be undone.</ div >
96+ ) : (
97+ < div className = "text-muted transition-colors group-hover:text-foreground" >
98+ Restores your project's files back to a snapshot taken at this point and deletes
99+ all messages after this point.
100+ </ div >
101+ ) }
102+ </ div >
103+ </ div >
104+ </ div >
105+ </ PopoverContent >
106+ </ Popover >
107+ </ div >
63108 )
64109}
65-
66- type CheckpointMenuItemProps = DropdownMenuItemProps & {
67- label : React . ReactNode
68- icon : "diff-single" | "diff-multiple" | "open-preview" | "history"
69- }
70-
71- const CheckpointMenuItem = ( { label, icon, ...props } : CheckpointMenuItemProps ) => (
72- < DropdownMenuItem { ...props } >
73- < div className = "flex flex-row-reverse gap-1" >
74- < div > { label } </ div >
75- < DropdownMenuShortcut >
76- < span className = { `codicon codicon-${ icon } ` } />
77- </ DropdownMenuShortcut >
78- </ div >
79- </ DropdownMenuItem >
80- )
0 commit comments