Skip to content

Commit cd552d6

Browse files
hobostayapexsloth
authored andcommitted
fix: clean up timeout in PlanSidebar to prevent memory leaks (pingdotgg#949)
Co-authored-by: hobostay <hobostay@users.noreply.github.com>
1 parent 06adf5e commit cd552d6

1 file changed

Lines changed: 18 additions & 2 deletions

File tree

apps/web/src/components/PlanSidebar.tsx

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { memo, useState, useCallback } from "react";
1+
import { memo, useState, useCallback, useRef, useEffect } from "react";
22
import { Badge } from "./ui/badge";
33
import { Button } from "./ui/button";
44
import { ScrollArea } from "./ui/scroll-area";
@@ -66,6 +66,7 @@ const PlanSidebar = memo(function PlanSidebar({
6666
const [proposedPlanExpanded, setProposedPlanExpanded] = useState(false);
6767
const [isSavingToWorkspace, setIsSavingToWorkspace] = useState(false);
6868
const [copied, setCopied] = useState(false);
69+
const copiedTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);
6970

7071
const planMarkdown = activeProposedPlan?.planMarkdown ?? null;
7172
const displayedPlanMarkdown = planMarkdown ? stripDisplayedPlanMarkdown(planMarkdown) : null;
@@ -74,8 +75,15 @@ const PlanSidebar = memo(function PlanSidebar({
7475
const handleCopyPlan = useCallback(() => {
7576
if (!planMarkdown) return;
7677
void navigator.clipboard.writeText(planMarkdown);
78+
if (copiedTimerRef.current != null) {
79+
clearTimeout(copiedTimerRef.current);
80+
}
81+
7782
setCopied(true);
78-
setTimeout(() => setCopied(false), 2000);
83+
copiedTimerRef.current = setTimeout(() => {
84+
setCopied(false);
85+
copiedTimerRef.current = null;
86+
}, 2000);
7987
}, [planMarkdown]);
8088

8189
const handleDownload = useCallback(() => {
@@ -120,6 +128,14 @@ const PlanSidebar = memo(function PlanSidebar({
120128
{/* Header */}
121129
<div className="flex h-12 shrink-0 items-center justify-between border-b border-border/60 px-3">
122130
<div className="flex items-center gap-2">
131+
// Cleanup timeout on unmount
132+
useEffect(() => {
133+
return () => {
134+
if (copiedTimerRef.current \!= null) {
135+
clearTimeout(copiedTimerRef.current);
136+
}
137+
};
138+
}, []);
123139
<Badge
124140
variant="secondary"
125141
className="rounded-md bg-blue-500/10 px-1.5 py-0 text-[10px] font-semibold tracking-wide text-blue-400 uppercase"

0 commit comments

Comments
 (0)