Skip to content

Commit 36d0ded

Browse files
bherilameta-codesync[bot]
authored andcommitted
recoil to jotai migration 13/n - review threads and comments
Summary: Continue the Recoil to Jotai migration by moving review thread and comment-related atoms. This allows components that render inline PR comments and review threads to use the simpler Jotai API. The gitHubPullRequestReviewThreads selector remains in Recoil because it's still consumed by gitHubPullRequestThreadsByCommit and gitHubPullRequestThreadsForCommit, which are used by components not yet migrated. Differential Revision: D92244729 fbshipit-source-id: 7484ba3508288d2fc606579749d20163a3b54ddc
1 parent 309a27e commit 36d0ded

7 files changed

Lines changed: 146 additions & 81 deletions

File tree

eden/contrib/reviewstack/src/PullRequestReviewComment.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,9 @@ import type {ID, GitObject} from './github/types';
99

1010
import PullRequestReviewCommentLineNumber from './PullRequestReviewCommentLineNumber';
1111
import TrustedRenderedMarkdown from './TrustedRenderedMarkdown';
12-
import {gitHubPullRequestCommentForID} from './recoil';
12+
import {gitHubPullRequestCommentForIDAtom} from './jotai';
1313
import {Box} from '@primer/react';
14-
import {useRecoilValue} from 'recoil';
14+
import {useAtomValue} from 'jotai';
1515

1616
type Props = {
1717
comment: {
@@ -23,7 +23,7 @@ type Props = {
2323
};
2424

2525
export default function PullRequestReviewComment({comment}: Props): React.ReactElement {
26-
const reviewComment = useRecoilValue(gitHubPullRequestCommentForID(comment.id));
26+
const reviewComment = useAtomValue(gitHubPullRequestCommentForIDAtom(comment.id));
2727
const commentID = comment.id;
2828
const commit = comment.originalCommit?.oid;
2929
const lineNumber = reviewComment?.originalLine;

eden/contrib/reviewstack/src/PullRequestTimeline.tsx

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,11 @@ import CommitLink from './CommitLink';
2626
import PendingLabel from './PendingLabel';
2727
import PullRequestReviewComment from './PullRequestReviewComment';
2828
import TrustedRenderedMarkdown from './TrustedRenderedMarkdown';
29-
import {gitHubOrgAndRepoAtom, gitHubPullRequestAtom} from './jotai';
30-
import {gitHubPullRequestReviewThreadsByFirstCommentID} from './recoil';
29+
import {
30+
gitHubOrgAndRepoAtom,
31+
gitHubPullRequestAtom,
32+
gitHubPullRequestReviewThreadsByFirstCommentIDAtom,
33+
} from './jotai';
3134
import {
3235
CheckCircleFillIcon,
3336
FileDiffIcon,
@@ -37,7 +40,6 @@ import {
3740
import {Box, StyledOcticon, Text} from '@primer/react';
3841
import {useAtomValue} from 'jotai';
3942
import React, {Suspense} from 'react';
40-
import {useRecoilValue} from 'recoil';
4143
import {notEmpty} from 'shared/utils';
4244

4345
export default function PullRequestTimeline(): React.ReactElement {
@@ -135,7 +137,7 @@ function TimelineBasicEvent(props: {children?: React.ReactNode}): React.ReactEle
135137
}
136138

137139
function PullRequestReview({item}: {item: PullRequestReviewItem}): React.ReactElement {
138-
const threadMap = useRecoilValue(gitHubPullRequestReviewThreadsByFirstCommentID);
140+
const threadMap = useAtomValue(gitHubPullRequestReviewThreadsByFirstCommentIDAtom);
139141
const comments = (item.comments.nodes ?? []).filter(notEmpty).flatMap((comment, index) => {
140142
// Check and see whether the first comment in the PullRequestReview corresponds
141143
// to a thread. If so, the comments in the thread are not available as

eden/contrib/reviewstack/src/PullRequestTimelineCommentInput.tsx

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,16 +8,14 @@
88
import PullRequestCommentInput from './PullRequestCommentInput';
99
import PullRequestReviewSelector from './PullRequestReviewSelector';
1010
import {PullRequestReviewEvent} from './generated/graphql';
11-
import {gitHubClientAtom, gitHubPullRequestAtom} from './jotai';
12-
import {gitHubPullRequestPendingReviewID} from './recoil';
11+
import {gitHubClientAtom, gitHubPullRequestAtom, gitHubPullRequestPendingReviewIDAtom} from './jotai';
1312
import useRefreshPullRequest from './useRefreshPullRequest';
1413
import {useAtomValue} from 'jotai';
1514
import {loadable} from 'jotai/utils';
1615
import {useCallback, useMemo, useState} from 'react';
17-
import {useRecoilValue} from 'recoil';
1816

1917
export default function PullRequestTimelineCommentInput(): React.ReactElement {
20-
const pendingReviewID = useRecoilValue(gitHubPullRequestPendingReviewID);
18+
const pendingReviewID = useAtomValue(gitHubPullRequestPendingReviewIDAtom);
2119
const refreshPullRequest = useRefreshPullRequest();
2220
const pullRequest = useAtomValue(gitHubPullRequestAtom);
2321
const [event, setEvent] = useState(PullRequestReviewEvent.Comment);

eden/contrib/reviewstack/src/PullRequestVersionCommitSelector.tsx

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,14 @@
88
import type {GitObjectID, VersionCommit} from './github/types';
99

1010
import PullRequestVersionCommitSelectorItem from './PullRequestVersionCommitSelectorItem';
11-
import {gitHubPullRequestComparableVersionsAtom} from './jotai';
12-
import {gitHubPullRequestSelectedVersionCommits} from './recoil';
11+
import {
12+
gitHubPullRequestComparableVersionsAtom,
13+
gitHubPullRequestSelectedVersionCommitsAtom,
14+
} from './jotai';
1315
import {shortOid} from './utils';
1416
import {ActionList, ActionMenu} from '@primer/react';
1517
import {useAtomValue} from 'jotai';
1618
import React from 'react';
17-
import {useRecoilValue} from 'recoil';
1819
import {notEmpty} from 'shared/utils';
1920

2021
type Props = {
@@ -32,7 +33,7 @@ export default React.memo(function PullRequestVersionCommitSelector({
3233
beforeCommitID: null,
3334
afterCommitID: '',
3435
};
35-
const commits = useRecoilValue(gitHubPullRequestSelectedVersionCommits);
36+
const commits = useAtomValue(gitHubPullRequestSelectedVersionCommitsAtom);
3637
const beforeIndex = getIndex(beforeCommitID, commits, -1);
3738
const afterIndex = getIndex(afterCommitID, commits, commits.length - 1);
3839

eden/contrib/reviewstack/src/jotai/atoms.ts

Lines changed: 117 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,11 @@ import type {
2020
} from '../generated/graphql';
2121
import type GitHubClient from '../github/GitHubClient';
2222
import type {DiffCommitIDs, DiffWithCommitIDs} from '../github/diffTypes';
23-
import type {GitHubPullRequestReviewThread, PullRequest} from '../github/pullRequestTimelineTypes';
23+
import type {
24+
GitHubPullRequestReviewThread,
25+
PullRequest,
26+
PullRequestReviewComment,
27+
} from '../github/pullRequestTimelineTypes';
2428
import type {PullsQueryInput, PullsWithPageInfo} from '../github/pullsTypes';
2529
import type {Blob, Commit, DateTime, GitObjectID, ID, Version, VersionCommit} from '../github/types';
2630

@@ -706,6 +710,118 @@ export const gitHubPullRequestsAtom = atomFamily(
706710
},
707711
);
708712

713+
// =============================================================================
714+
// Pull Request Pending Review ID
715+
// =============================================================================
716+
717+
/**
718+
* Migrated from: gitHubPullRequestPendingReviewID selector in recoil.ts
719+
*
720+
* A PR should have at most a single pending review per user. Any inline
721+
* comments made will either create a new pending review or be added to the
722+
* existing one.
723+
*/
724+
export const gitHubPullRequestPendingReviewIDAtom = atom<ID | null>(get => {
725+
const pullRequest = get(gitHubPullRequestAtom);
726+
const pendingReview = (pullRequest?.timelineItems?.nodes ?? []).find(
727+
item => item?.__typename === 'PullRequestReview' && item.state === 'PENDING',
728+
);
729+
return (pendingReview as {id: ID} | undefined)?.id ?? null;
730+
});
731+
732+
// =============================================================================
733+
// Pull Request Review Threads
734+
// =============================================================================
735+
736+
/**
737+
* Migrated from: gitHubPullRequestReviewThreads selector in recoil.ts
738+
*
739+
* Extracts and normalizes review threads from the pull request.
740+
*/
741+
export const gitHubPullRequestReviewThreadsAtom = atom<GitHubPullRequestReviewThread[]>(get => {
742+
const pullRequest = get(gitHubPullRequestAtom);
743+
return (pullRequest?.reviewThreads.nodes ?? []).filter(notEmpty).map(reviewThread => {
744+
const {originalLine, diffSide, comments} = reviewThread;
745+
const normalizedComments = (comments?.nodes ?? [])
746+
.map(comment => {
747+
if (comment == null) {
748+
return null;
749+
}
750+
751+
const {id, author, originalCommit, path, state, bodyHTML} = comment;
752+
const reviewThreadComment = {
753+
id,
754+
author: author ?? null,
755+
originalCommit,
756+
path,
757+
state,
758+
bodyHTML,
759+
};
760+
return reviewThreadComment;
761+
})
762+
.filter(notEmpty);
763+
const firstCommentID = normalizedComments[0].id;
764+
return {
765+
firstCommentID,
766+
originalLine,
767+
diffSide,
768+
comments: normalizedComments,
769+
};
770+
});
771+
});
772+
773+
/**
774+
* Migrated from: gitHubPullRequestReviewThreadsByFirstCommentID selector in recoil.ts
775+
*
776+
* Returns review threads indexed by the ID of their first comment.
777+
* Used to look up thread information when rendering inline comments.
778+
*/
779+
export const gitHubPullRequestReviewThreadsByFirstCommentIDAtom = atom<{
780+
[id: ID]: GitHubPullRequestReviewThread;
781+
}>(get => {
782+
return Object.fromEntries(
783+
get(gitHubPullRequestReviewThreadsAtom).map(thread => [thread.firstCommentID, thread]),
784+
);
785+
});
786+
787+
// =============================================================================
788+
// Pull Request Comment Lookup
789+
// =============================================================================
790+
791+
// Note: PullRequestReviewComment type is imported from pullRequestTimelineTypes.ts
792+
793+
/**
794+
* Internal atom that indexes all review comments by their ID.
795+
*/
796+
const gitHubPullRequestReviewCommentsByIDAtom = atom<Map<ID, PullRequestReviewComment>>(get => {
797+
const reviewThreads = get(gitHubPullRequestReviewThreadsAtom);
798+
const commentsByID = new Map<ID, PullRequestReviewComment>();
799+
reviewThreads.forEach(({originalLine, comments}) => {
800+
comments.forEach(comment => {
801+
const {id} = comment;
802+
if (id != null) {
803+
commentsByID.set(id, {originalLine, comment});
804+
}
805+
});
806+
});
807+
return commentsByID;
808+
});
809+
810+
/**
811+
* Migrated from: gitHubPullRequestCommentForID selectorFamily in recoil.ts
812+
*
813+
* Looks up a review comment by its ID. Returns the comment with its
814+
* original line number for display purposes.
815+
*/
816+
export const gitHubPullRequestCommentForIDAtom = atomFamily(
817+
(id: ID) =>
818+
atom<PullRequestReviewComment | null>(get => {
819+
const commentsByID = get(gitHubPullRequestReviewCommentsByIDAtom);
820+
return commentsByID.get(id) ?? null;
821+
}),
822+
(a, b) => a === b,
823+
);
824+
709825
// =============================================================================
710826
// GitHub Blob
711827
// =============================================================================

eden/contrib/reviewstack/src/jotai/index.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,10 @@ export {
4141
gitHubThreadsForDiffFileAtom,
4242
gitHubPullRequestLineToPositionForFileAtom,
4343
gitHubPullRequestCheckRunsAtom,
44+
gitHubPullRequestPendingReviewIDAtom,
45+
gitHubPullRequestReviewThreadsAtom,
46+
gitHubPullRequestReviewThreadsByFirstCommentIDAtom,
47+
gitHubPullRequestCommentForIDAtom,
4448
} from './atoms';
4549

4650
export type {

eden/contrib/reviewstack/src/recoil.ts

Lines changed: 9 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,6 @@ import type {CommitChange, DiffWithCommitIDs} from './github/diffTypes';
1010
import type {
1111
CommitData,
1212
PullRequestCommitItem,
13-
PullRequestReviewComment,
14-
PullRequestReviewItem,
1513
GitHubPullRequestReviewThread,
1614
PullRequest,
1715
} from './github/pullRequestTimelineTypes';
@@ -22,15 +20,14 @@ import type {
2220
DateTime,
2321
ForcePushEvent,
2422
GitObjectID,
25-
ID,
2623
Version,
2724
VersionCommit,
2825
} from './github/types';
2926
import type {LineToPosition} from './lineToPosition';
3027
import type {RecoilValueReadOnly} from 'recoil';
3128

3229
import {lineToPosition} from './diffServiceClient';
33-
import {DiffSide, PullRequestReviewState} from './generated/graphql';
30+
import {DiffSide} from './generated/graphql';
3431
import CachingGitHubClient, {openDatabase} from './github/CachingGitHubClient';
3532
import GraphQLGitHubClient from './github/GraphQLGitHubClient';
3633
import {diffCommits, diffCommitWithParent} from './github/diff';
@@ -137,22 +134,8 @@ export const gitHubPullRequestBaseRef = selector<GitObjectID | null>({
137134
},
138135
});
139136

140-
/**
141-
* A PR should have at most a single pending review per user. Any inline
142-
* comments made will either create a new pending review or be added to the
143-
* existing one.
144-
*/
145-
export const gitHubPullRequestPendingReviewID = selector<ID | null>({
146-
key: 'gitHubPullRequestPendingReviewID',
147-
get: ({get}) => {
148-
const pullRequest = get(gitHubPullRequest);
149-
const pendingReview = (pullRequest?.timelineItems?.nodes ?? []).find(
150-
item =>
151-
item?.__typename === 'PullRequestReview' && item.state === PullRequestReviewState.Pending,
152-
) as PullRequestReviewItem;
153-
return pendingReview?.id ?? null;
154-
},
155-
});
137+
// NOTE: gitHubPullRequestPendingReviewID has been migrated to Jotai.
138+
// See gitHubPullRequestPendingReviewIDAtom in jotai/atoms.ts
156139

157140
export const gitHubPullRequestCommits = selector<CommitData[]>({
158141
key: 'gitHubPullRequestCommits',
@@ -472,43 +455,11 @@ export const gitHubPullRequestReviewThreads = selector<GitHubPullRequestReviewTh
472455
},
473456
});
474457

475-
export const gitHubPullRequestReviewThreadsByFirstCommentID = selector<{
476-
[id: ID]: GitHubPullRequestReviewThread;
477-
}>({
478-
key: 'gitHubPullRequestReviewThreadsByFirstCommentID',
479-
get: ({get}) => {
480-
return Object.fromEntries(
481-
get(gitHubPullRequestReviewThreads).map(thread => [thread.firstCommentID, thread]),
482-
);
483-
},
484-
});
485-
486-
const gitHubPullRequestReviewCommentsByID = selector<Map<ID, PullRequestReviewComment>>({
487-
key: 'gitHubPullRequestReviewCommentsByID',
488-
get: ({get}) => {
489-
const reviewThreads = get(gitHubPullRequestReviewThreads);
490-
const commentsByID = new Map();
491-
reviewThreads.forEach(({originalLine, comments}) => {
492-
comments.forEach(comment => {
493-
const {id} = comment;
494-
if (id != null) {
495-
commentsByID.set(id, {originalLine, comment});
496-
}
497-
});
498-
});
499-
return commentsByID;
500-
},
501-
});
458+
// NOTE: gitHubPullRequestReviewThreadsByFirstCommentID has been migrated to Jotai.
459+
// See gitHubPullRequestReviewThreadsByFirstCommentIDAtom in jotai/atoms.ts
502460

503-
export const gitHubPullRequestCommentForID = selectorFamily<PullRequestReviewComment | null, ID>({
504-
key: 'gitHubPullRequestCommentForID',
505-
get:
506-
id =>
507-
({get}) => {
508-
const commentsByID = get(gitHubPullRequestReviewCommentsByID);
509-
return commentsByID.get(id) ?? null;
510-
},
511-
});
461+
// NOTE: gitHubPullRequestCommentForID has been migrated to Jotai.
462+
// See gitHubPullRequestCommentForIDAtom in jotai/atoms.ts
512463

513464
export const gitHubPullRequestNewCommentInputCell = atom<{
514465
lineNumber: number;
@@ -855,15 +806,8 @@ export const gitHubPullRequestComparableVersions = atom<ComparableVersions>({
855806
}),
856807
});
857808

858-
export const gitHubPullRequestSelectedVersionCommits = selector<VersionCommit[]>({
859-
key: 'gitHubPullRequestSelectedVersionCommits',
860-
get: ({get}) => {
861-
const [versions, selectedVersionIndex] = get(
862-
waitForAll([gitHubPullRequestVersions, gitHubPullRequestSelectedVersionIndex]),
863-
);
864-
return versions[selectedVersionIndex]?.commits ?? [];
865-
},
866-
});
809+
// NOTE: gitHubPullRequestSelectedVersionCommits has been migrated to Jotai.
810+
// See gitHubPullRequestSelectedVersionCommitsAtom in jotai/atoms.ts
867811

868812
// NOTE: gitHubPullRequestVersionDiff has been migrated to Jotai.
869813
// See gitHubPullRequestVersionDiffAtom in jotai/atoms.ts

0 commit comments

Comments
 (0)