diff --git a/src/renderer/components/PRTreeView.tsx b/src/renderer/components/PRTreeView.tsx index ee0fd0b0..0a2471eb 100644 --- a/src/renderer/components/PRTreeView.tsx +++ b/src/renderer/components/PRTreeView.tsx @@ -160,7 +160,8 @@ interface PRTreeViewProps { onTogglePRSelection: (prId: string, checked: boolean) => void; onToggleGroupSelection: (prIds: string[], checked: boolean) => void; onPRClick: (pr: PullRequest) => void; - onCloseGroup: (prIds: string[]) => void; + onCloseGroup: (groupId: string, prIds: string[]) => void; + closingGroupId: string | null; } // Helper function to format date and time @@ -214,6 +215,7 @@ export function PRTreeView({ onToggleGroupSelection, onPRClick, onCloseGroup, + closingGroupId, }: PRTreeViewProps) { const treeItems = useMemo( () => buildTreeItems(prsWithMetadata), @@ -414,31 +416,34 @@ export function PRTreeView({ )} - {item.data.closablePRIds && item.data.closablePRIds.length > 0 && hoveredGroup === item.index && ( + {item.data.closablePRIds && item.data.closablePRIds.length > 0 && (hoveredGroup === item.index || closingGroupId === item.index) && (
{ + if (closingGroupId === item.index) return; event.stopPropagation(); - onCloseGroup(item.data.closablePRIds ?? []); - setHoveredGroup(null); + onCloseGroup(item.index as string, item.data.closablePRIds ?? []); }} onKeyDown={(event) => { + if (closingGroupId === item.index) return; if (event.key === 'Enter' || event.key === ' ') { event.preventDefault(); event.stopPropagation(); - onCloseGroup(item.data.closablePRIds ?? []); - setHoveredGroup(null); + onCloseGroup(item.index as string, item.data.closablePRIds ?? []); } }} className={cn( - "ml-3 px-2 py-1 text-xs font-medium rounded border transition-colors cursor-pointer", + "ml-3 px-2 py-1 text-xs font-medium rounded border transition-colors", + closingGroupId === item.index + ? "cursor-wait opacity-75" + : "cursor-pointer", theme === "dark" ? "border-red-500/60 text-red-300 hover:bg-red-900/40" : "border-red-400 text-red-600 hover:bg-red-50" )} > - Close unmerged PRs? + {closingGroupId === item.index ? "Closing..." : "Close unmerged PRs?"}
)} diff --git a/src/renderer/views/PRListView.tsx b/src/renderer/views/PRListView.tsx index 9fe8ee96..c907c856 100644 --- a/src/renderer/views/PRListView.tsx +++ b/src/renderer/views/PRListView.tsx @@ -55,6 +55,7 @@ export default function PRListView() { const [showStatusDropdown, setShowStatusDropdown] = useState(false); const statusDropdownRef = useRef(null); const [isClosing, setIsClosing] = useState(false); + const [closingGroupId, setClosingGroupId] = useState(null); const sortBy = prListFilters.sortBy; const selectedAuthors = useMemo( @@ -524,8 +525,10 @@ export default function PRListView() { }, [closePRIds, closableSelectedPRIds]); const handleCloseGroup = useCallback( - async (prIds: string[]) => { + async (groupId: string, prIds: string[]) => { + setClosingGroupId(groupId); await closePRIds(prIds); + setClosingGroupId(null); }, [closePRIds], ); @@ -920,6 +923,7 @@ export default function PRListView() { onToggleGroupSelection={handleGroupSelection} onPRClick={handlePRClick} onCloseGroup={handleCloseGroup} + closingGroupId={closingGroupId} /> )}