|
|
@@ -1,29 +1,22 @@
|
|
|
import { useState, useEffect, useCallback } from "react"
|
|
|
-import { DotsHorizontalIcon } from "@radix-ui/react-icons"
|
|
|
-import { DropdownMenuItemProps } from "@radix-ui/react-dropdown-menu"
|
|
|
+import { CheckIcon, Cross2Icon } from "@radix-ui/react-icons"
|
|
|
|
|
|
import { vscode } from "../../../utils/vscode"
|
|
|
|
|
|
-import {
|
|
|
- Button,
|
|
|
- DropdownMenu,
|
|
|
- DropdownMenuTrigger,
|
|
|
- DropdownMenuContent,
|
|
|
- DropdownMenuItem,
|
|
|
- DropdownMenuShortcut,
|
|
|
-} from "@/components/ui"
|
|
|
+import { Button, Popover, PopoverContent, PopoverTrigger } from "@/components/ui"
|
|
|
|
|
|
type CheckpointMenuProps = {
|
|
|
ts: number
|
|
|
commitHash: string
|
|
|
+ currentCheckpointHash?: string
|
|
|
}
|
|
|
|
|
|
-export const CheckpointMenu = ({ ts, commitHash }: CheckpointMenuProps) => {
|
|
|
+export const CheckpointMenu = ({ ts, commitHash, currentCheckpointHash }: CheckpointMenuProps) => {
|
|
|
const [portalContainer, setPortalContainer] = useState<HTMLElement>()
|
|
|
+ const [isOpen, setIsOpen] = useState(false)
|
|
|
+ const [isConfirming, setIsConfirming] = useState(false)
|
|
|
|
|
|
- const onTaskDiff = useCallback(() => {
|
|
|
- vscode.postMessage({ type: "checkpointDiff", payload: { ts, commitHash, mode: "full" } })
|
|
|
- }, [ts, commitHash])
|
|
|
+ const isCurrent = currentCheckpointHash === commitHash
|
|
|
|
|
|
const onCheckpointDiff = useCallback(() => {
|
|
|
vscode.postMessage({ type: "checkpointDiff", payload: { ts, commitHash, mode: "checkpoint" } })
|
|
|
@@ -31,10 +24,12 @@ export const CheckpointMenu = ({ ts, commitHash }: CheckpointMenuProps) => {
|
|
|
|
|
|
const onPreview = useCallback(() => {
|
|
|
vscode.postMessage({ type: "checkpointRestore", payload: { ts, commitHash, mode: "preview" } })
|
|
|
+ setIsOpen(false)
|
|
|
}, [ts, commitHash])
|
|
|
|
|
|
const onRestore = useCallback(() => {
|
|
|
vscode.postMessage({ type: "checkpointRestore", payload: { ts, commitHash, mode: "restore" } })
|
|
|
+ setIsOpen(false)
|
|
|
}, [ts, commitHash])
|
|
|
|
|
|
useEffect(() => {
|
|
|
@@ -47,34 +42,68 @@ export const CheckpointMenu = ({ ts, commitHash }: CheckpointMenuProps) => {
|
|
|
}, [])
|
|
|
|
|
|
return (
|
|
|
- <DropdownMenu>
|
|
|
- <DropdownMenuTrigger asChild>
|
|
|
- <Button variant="ghost" size="icon">
|
|
|
- <DotsHorizontalIcon />
|
|
|
- </Button>
|
|
|
- </DropdownMenuTrigger>
|
|
|
- <DropdownMenuContent container={portalContainer} align="end">
|
|
|
- <CheckpointMenuItem label="Checkpoint Diff" icon="diff-single" onClick={onCheckpointDiff} />
|
|
|
- <CheckpointMenuItem label="Task Diff" icon="diff-multiple" onClick={onTaskDiff} />
|
|
|
- <CheckpointMenuItem label="Preview" icon="open-preview" onClick={onPreview} />
|
|
|
- <CheckpointMenuItem label="Restore" icon="history" onClick={onRestore} />
|
|
|
- </DropdownMenuContent>
|
|
|
- </DropdownMenu>
|
|
|
+ <div className="flex flex-row gap-1">
|
|
|
+ <Button variant="ghost" size="icon" onClick={onCheckpointDiff}>
|
|
|
+ <span className="codicon codicon-diff-single" />
|
|
|
+ </Button>
|
|
|
+ <Popover
|
|
|
+ open={isOpen}
|
|
|
+ onOpenChange={(open) => {
|
|
|
+ setIsOpen(open)
|
|
|
+ setIsConfirming(false)
|
|
|
+ }}>
|
|
|
+ <PopoverTrigger asChild>
|
|
|
+ <Button variant="ghost" size="icon">
|
|
|
+ <span className="codicon codicon-history" />
|
|
|
+ </Button>
|
|
|
+ </PopoverTrigger>
|
|
|
+ <PopoverContent align="end" container={portalContainer}>
|
|
|
+ <div className="flex flex-col gap-2">
|
|
|
+ {!isCurrent && (
|
|
|
+ <div className="flex flex-col gap-1 group hover:text-foreground">
|
|
|
+ <Button variant="secondary" onClick={onPreview}>
|
|
|
+ Restore Files
|
|
|
+ </Button>
|
|
|
+ <div className="text-muted transition-colors group-hover:text-foreground">
|
|
|
+ Restores your project's files back to a snapshot taken at this point.
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ )}
|
|
|
+ <div className="flex flex-col gap-1 group hover:text-foreground">
|
|
|
+ <div className="flex flex-col gap-1 group hover:text-foreground">
|
|
|
+ {!isConfirming ? (
|
|
|
+ <Button variant="secondary" onClick={() => setIsConfirming(true)}>
|
|
|
+ Restore Files & Task
|
|
|
+ </Button>
|
|
|
+ ) : (
|
|
|
+ <>
|
|
|
+ <Button variant="default" onClick={onRestore} className="grow">
|
|
|
+ <div className="flex flex-row gap-1">
|
|
|
+ <CheckIcon />
|
|
|
+ <div>Confirm</div>
|
|
|
+ </div>
|
|
|
+ </Button>
|
|
|
+ <Button variant="secondary" onClick={() => setIsConfirming(false)}>
|
|
|
+ <div className="flex flex-row gap-1">
|
|
|
+ <Cross2Icon />
|
|
|
+ <div>Cancel</div>
|
|
|
+ </div>
|
|
|
+ </Button>
|
|
|
+ </>
|
|
|
+ )}
|
|
|
+ {isConfirming ? (
|
|
|
+ <div className="text-destructive font-bold">This action cannot be undone.</div>
|
|
|
+ ) : (
|
|
|
+ <div className="text-muted transition-colors group-hover:text-foreground">
|
|
|
+ Restores your project's files back to a snapshot taken at this point and deletes
|
|
|
+ all messages after this point.
|
|
|
+ </div>
|
|
|
+ )}
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </PopoverContent>
|
|
|
+ </Popover>
|
|
|
+ </div>
|
|
|
)
|
|
|
}
|
|
|
-
|
|
|
-type CheckpointMenuItemProps = DropdownMenuItemProps & {
|
|
|
- label: React.ReactNode
|
|
|
- icon: "diff-single" | "diff-multiple" | "open-preview" | "history"
|
|
|
-}
|
|
|
-
|
|
|
-const CheckpointMenuItem = ({ label, icon, ...props }: CheckpointMenuItemProps) => (
|
|
|
- <DropdownMenuItem {...props}>
|
|
|
- <div className="flex flex-row-reverse gap-1">
|
|
|
- <div>{label}</div>
|
|
|
- <DropdownMenuShortcut>
|
|
|
- <span className={`codicon codicon-${icon}`} />
|
|
|
- </DropdownMenuShortcut>
|
|
|
- </div>
|
|
|
- </DropdownMenuItem>
|
|
|
-)
|