From 83f246bde68bd99eaf470ad2ef7a87e6dd585f03 Mon Sep 17 00:00:00 2001 From: Neil <4138956+nwparker@users.noreply.github.com> Date: Sat, 30 May 2026 20:07:25 -0700 Subject: [PATCH] Derive GitHub reviewer picker active index during render (#3114) --- .../src/components/GitHubItemDialog.tsx | 23 +++++++++++++++---- .../src/components/PullRequestPage.tsx | 23 +++++++++++++++---- src/renderer/src/components/TaskPage.tsx | 23 +++++++++++++++---- 3 files changed, 57 insertions(+), 12 deletions(-) diff --git a/src/renderer/src/components/GitHubItemDialog.tsx b/src/renderer/src/components/GitHubItemDialog.tsx index c960eb05338..ffec45b0a21 100644 --- a/src/renderer/src/components/GitHubItemDialog.tsx +++ b/src/renderer/src/components/GitHubItemDialog.tsx @@ -393,7 +393,7 @@ function PRReviewersPanel({ const [reviewerInput, setReviewerInput] = useState('') const [reviewerPickerSide, setReviewerPickerSide] = useState<'top' | 'bottom'>('bottom') const [reviewerPickerMaxHeight, setReviewerPickerMaxHeight] = useState(null) - const [activeReviewerIndex, setActiveReviewerIndex] = useState(0) + const [activeReviewerCursor, setActiveReviewerCursor] = useState({ resetKey: '', index: 0 }) const [submitting, setSubmitting] = useState(false) const [localReviewRequests, setLocalReviewRequests] = useState( () => item.reviewRequests ?? [] @@ -558,9 +558,24 @@ function PRReviewersPanel({ [everyoneElseReviewerRows, suggestedReviewerRows] ) - useEffect(() => { - setActiveReviewerIndex(0) - }, [reviewerQuery, actionableReviewerRows.length]) + const reviewerCursorResetKey = `${reviewerQuery}\u0000${actionableReviewerRows.length}` + if (activeReviewerCursor.resetKey !== reviewerCursorResetKey) { + setActiveReviewerCursor({ resetKey: reviewerCursorResetKey, index: 0 }) + } + const activeReviewerIndex = + activeReviewerCursor.resetKey === reviewerCursorResetKey ? activeReviewerCursor.index : 0 + const setActiveReviewerIndex = useCallback( + (nextIndex: number | ((current: number) => number)): void => { + setActiveReviewerCursor((current) => { + const currentIndex = current.resetKey === reviewerCursorResetKey ? current.index : 0 + return { + resetKey: reviewerCursorResetKey, + index: typeof nextIndex === 'function' ? nextIndex(currentIndex) : nextIndex + } + }) + }, + [reviewerCursorResetKey] + ) const hasReviewerMetadata = item.reviewDecision !== undefined || diff --git a/src/renderer/src/components/PullRequestPage.tsx b/src/renderer/src/components/PullRequestPage.tsx index 0d89636d2ea..d5505a94054 100644 --- a/src/renderer/src/components/PullRequestPage.tsx +++ b/src/renderer/src/components/PullRequestPage.tsx @@ -472,7 +472,7 @@ function PRReviewersPanel({ const [reviewerInput, setReviewerInput] = useState('') const [reviewerPickerSide, setReviewerPickerSide] = useState<'top' | 'bottom'>('bottom') const [reviewerPickerMaxHeight, setReviewerPickerMaxHeight] = useState(null) - const [activeReviewerIndex, setActiveReviewerIndex] = useState(0) + const [activeReviewerCursor, setActiveReviewerCursor] = useState({ resetKey: '', index: 0 }) const [submitting, setSubmitting] = useState(false) const [localReviewRequests, setLocalReviewRequests] = useState( () => item.reviewRequests ?? [] @@ -637,9 +637,24 @@ function PRReviewersPanel({ [everyoneElseReviewerRows, suggestedReviewerRows] ) - useEffect(() => { - setActiveReviewerIndex(0) - }, [reviewerQuery, actionableReviewerRows.length]) + const reviewerCursorResetKey = `${reviewerQuery}\u0000${actionableReviewerRows.length}` + if (activeReviewerCursor.resetKey !== reviewerCursorResetKey) { + setActiveReviewerCursor({ resetKey: reviewerCursorResetKey, index: 0 }) + } + const activeReviewerIndex = + activeReviewerCursor.resetKey === reviewerCursorResetKey ? activeReviewerCursor.index : 0 + const setActiveReviewerIndex = useCallback( + (nextIndex: number | ((current: number) => number)): void => { + setActiveReviewerCursor((current) => { + const currentIndex = current.resetKey === reviewerCursorResetKey ? current.index : 0 + return { + resetKey: reviewerCursorResetKey, + index: typeof nextIndex === 'function' ? nextIndex(currentIndex) : nextIndex + } + }) + }, + [reviewerCursorResetKey] + ) const hasReviewerMetadata = item.reviewDecision !== undefined || diff --git a/src/renderer/src/components/TaskPage.tsx b/src/renderer/src/components/TaskPage.tsx index 9ca8825ce4c..a0fc7700258 100644 --- a/src/renderer/src/components/TaskPage.tsx +++ b/src/renderer/src/components/TaskPage.tsx @@ -1434,7 +1434,7 @@ function PRReviewCell({ reviewRequests: item.reviewRequests })) const patchWorkItem = useAppStore((s) => s.patchWorkItem) - const [activeReviewerIndex, setActiveReviewerIndex] = useState(0) + const [activeReviewerCursor, setActiveReviewerCursor] = useState({ resetKey: '', index: 0 }) const [submitting, setSubmitting] = useState(false) const settings = useAppStore((s) => s.settings) const reviewerInputRef = useRef(null) @@ -1576,9 +1576,24 @@ function PRReviewCell({ [everyoneElseReviewerRows, suggestedReviewerRows] ) - useEffect(() => { - setActiveReviewerIndex(0) - }, [reviewerQuery, actionableReviewerRows.length]) + const reviewerCursorResetKey = `${reviewerQuery}\u0000${actionableReviewerRows.length}` + if (activeReviewerCursor.resetKey !== reviewerCursorResetKey) { + setActiveReviewerCursor({ resetKey: reviewerCursorResetKey, index: 0 }) + } + const activeReviewerIndex = + activeReviewerCursor.resetKey === reviewerCursorResetKey ? activeReviewerCursor.index : 0 + const setActiveReviewerIndex = useCallback( + (nextIndex: number | ((current: number) => number)): void => { + setActiveReviewerCursor((current) => { + const currentIndex = current.resetKey === reviewerCursorResetKey ? current.index : 0 + return { + resetKey: reviewerCursorResetKey, + index: typeof nextIndex === 'function' ? nextIndex(currentIndex) : nextIndex + } + }) + }, + [reviewerCursorResetKey] + ) if (item.type !== 'pr') { return Issue