| ... | ... | @@ -86,6 +86,15 @@ const PlanSidebar = memo(function PlanSidebar({ |
| 86 | 86 | }, 2000); |
| 87 | 87 | }, [planMarkdown]); |
| 88 | 88 | |
| 89 | // Cleanup timeout on unmount |
| 90 | useEffect(() => { |
| 91 | return () => { |
| 92 | if (copiedTimerRef.current != null) { |
| 93 | clearTimeout(copiedTimerRef.current); |
| 94 | } |
| 95 | }; |
| 96 | }, []); |
| 97 | |
| 89 | 98 | const handleDownload = useCallback(() => { |
| 90 | 99 | if (!planMarkdown) return; |
| 91 | 100 | const filename = buildProposedPlanMarkdownFilename(planMarkdown); |
| ... | ... | @@ -128,14 +137,6 @@ const PlanSidebar = memo(function PlanSidebar({ |
| 128 | 137 | {/* Header */} |
| 129 | 138 | <div className="flex h-12 shrink-0 items-center justify-between border-b border-border/60 px-3"> |
| 130 | 139 | <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 | | }, []); |
| 139 | 140 | <Badge |
| 140 | 141 | variant="secondary" |
| 141 | 142 | className="rounded-md bg-blue-500/10 px-1.5 py-0 text-[10px] font-semibold tracking-wide text-blue-400 uppercase" |