History

Add copy-to-clipboard action for proposed plan card (#1620)

Julius Marminge committed 7 months ago

Commit 60f7ae81 parent 867cf4c1 file · +17 −0Browse files

Unified · Split

apps/web/src/components/chat/ProposedPlanCard.tsx+17−0
@@ -25,6 +25,7 @@ import { · 24 unmodified lines
25} from "../ui/dialog";25} from "../ui/dialog";
26import { toastManager } from "../ui/toast";26import { toastManager } from "../ui/toast";
27import { readNativeApi } from "~/nativeApi";27import { readNativeApi } from "~/nativeApi";
28import { useCopyToClipboard } from "~/hooks/useCopyToClipboard";
28 29
29export const ProposedPlanCard = memo(function ProposedPlanCard({30export const ProposedPlanCard = memo(function ProposedPlanCard({
30 planMarkdown,31 planMarkdown,
@@ -39,6 +40,15 @@ export const ProposedPlanCard = memo(function ProposedPlanCard({ · 8 unmodified lines
39 const [isSaveDialogOpen, setIsSaveDialogOpen] = useState(false);40 const [isSaveDialogOpen, setIsSaveDialogOpen] = useState(false);
40 const [savePath, setSavePath] = useState("");41 const [savePath, setSavePath] = useState("");
41 const [isSavingToWorkspace, setIsSavingToWorkspace] = useState(false);42 const [isSavingToWorkspace, setIsSavingToWorkspace] = useState(false);
43 const { copyToClipboard, isCopied } = useCopyToClipboard({
44 onError: (error) => {
45 toastManager.add({
46 type: "error",
47 title: "Could not copy plan",
48 description: error instanceof Error ? error.message : "An error occurred while copying.",
49 });
50 },
51 });
42 const savePathInputId = useId();52 const savePathInputId = useId();
43 const title = proposedPlanTitle(planMarkdown) ?? "Proposed plan";53 const title = proposedPlanTitle(planMarkdown) ?? "Proposed plan";
44 const lineCount = planMarkdown.split("\n").length;54 const lineCount = planMarkdown.split("\n").length;
@@ -54,6 +64,10 @@ export const ProposedPlanCard = memo(function ProposedPlanCard({ · 9 unmodified lines
54 downloadPlanAsTextFile(downloadFilename, saveContents);64 downloadPlanAsTextFile(downloadFilename, saveContents);
55 };65 };
56 66
67 const handleCopyPlan = () => {
68 copyToClipboard(saveContents);
69 };
70
57 const openSaveDialog = () => {71 const openSaveDialog = () => {
58 if (!workspaceRoot) {72 if (!workspaceRoot) {
59 toastManager.add({73 toastManager.add({
@@ -127,6 +141,9 @@ export const ProposedPlanCard = memo(function ProposedPlanCard({ · 67 unmodified lines
127 <EllipsisIcon aria-hidden="true" className="size-4" />141 <EllipsisIcon aria-hidden="true" className="size-4" />
128 </MenuTrigger>142 </MenuTrigger>
129 <MenuPopup align="end">143 <MenuPopup align="end">
144 <MenuItem onClick={handleCopyPlan}>
145 {isCopied ? "Copied!" : "Copy to clipboard"}
146 </MenuItem>
130 <MenuItem onClick={handleDownload}>Download as markdown</MenuItem>147 <MenuItem onClick={handleDownload}>Download as markdown</MenuItem>
131 <MenuItem onClick={openSaveDialog} disabled={!workspaceRoot || isSavingToWorkspace}>148 <MenuItem onClick={openSaveDialog} disabled={!workspaceRoot || isSavingToWorkspace}>
132 Save to workspace149 Save to workspace