diff --git a/src/renderer/src/components/GitLabItemDialog.tsx b/src/renderer/src/components/GitLabItemDialog.tsx index ae36d2176ca..b19cd88125a 100644 --- a/src/renderer/src/components/GitLabItemDialog.tsx +++ b/src/renderer/src/components/GitLabItemDialog.tsx @@ -311,7 +311,17 @@ export default function GitLabItemDialog({ const [loading, setLoading] = useState(false) const [error, setError] = useState(null) const [refreshNonce, setRefreshNonce] = useState(0) - const [commentDraft, setCommentDraft] = useState('') + const itemId = item?.id ?? null + const [commentDraftState, setCommentDraftState] = useState<{ + itemId: string | null + value: string + }>(() => ({ itemId, value: '' })) + const commentDraft = commentDraftState.itemId === itemId ? commentDraftState.value : '' + if (commentDraftState.itemId !== itemId) { + // Why: comment drafts are tied to one GitLab item, so switching the sheet + // target must not leave a draft that could post to the wrong MR/issue. + setCommentDraftState({ itemId, value: '' }) + } const [commentSubmitting, setCommentSubmitting] = useState(false) const [resolvingThreadId, setResolvingThreadId] = useState(null) const [editingDetails, setEditingDetails] = useState(false) @@ -334,6 +344,12 @@ export default function GitLabItemDialog({ const [retryingJobId, setRetryingJobId] = useState(null) const [actionInFlight, setActionInFlight] = useState<'close' | 'reopen' | 'merge' | null>(null) const mountedRef = useMountedRef() + const updateCommentDraft = useCallback( + (value: string): void => { + setCommentDraftState({ itemId, value }) + }, + [itemId] + ) useEffect(() => { if (!item || !repoPath) { @@ -373,10 +389,9 @@ export default function GitLabItemDialog({ } }, [item, repoPath, refreshNonce]) - // Why: clear the comment draft when the sheet target changes so the - // user doesn't accidentally post one MR's draft against another. + // Why: clear item-scoped dialog state when the sheet target changes. The + // top-level comment draft is reconciled during render so it cannot flash stale. useEffect(() => { - setCommentDraft('') setEditingDetails(false) setTitleDraft('') setBodyDraft('') @@ -812,7 +827,9 @@ export default function GitLabItemDialog({ : await window.api.gl.addIssueComment({ repoPath, number: item.number, body }) if (res.ok) { if (mountedRef.current) { - setCommentDraft('') + setCommentDraftState((current) => + current.itemId === itemId ? { itemId, value: '' } : current + ) handleRefresh() } } else { @@ -825,7 +842,7 @@ export default function GitLabItemDialog({ setCommentSubmitting(false) } } - }, [commentDraft, item, repoPath, mountedRef, handleRefresh]) + }, [commentDraft, item, itemId, repoPath, mountedRef, handleRefresh]) const handleResolveDiscussion = useCallback( async (threadId: string, resolved: boolean): Promise => { @@ -1391,7 +1408,7 @@ export default function GitLabItemDialog({