diff --git a/src/lib/api/keys.ts b/src/lib/api/keys.ts index 51be7f8..81dffd6 100644 --- a/src/lib/api/keys.ts +++ b/src/lib/api/keys.ts @@ -3,3 +3,4 @@ export const issuesQueryKey = (repoDid: string) => ['issues', repoDid] as const; export const issueQueryKey = (repoDid: string, issueRef: string) => ['issue', repoDid, issueRef] as const; export const pullsQueryKey = (repoDid: string) => ['pulls', repoDid] as const; export const pullQueryKey = (repoDid: string, pullRef: string) => ['pull', repoDid, pullRef] as const; +export const pullPatchQueryKey = (pullUri: string, roundIndex: number) => ['pull-patch', pullUri, roundIndex] as const; diff --git a/src/lib/preloading.tsx b/src/lib/preloading.tsx index ae6cf6a..f8005b4 100644 --- a/src/lib/preloading.tsx +++ b/src/lib/preloading.tsx @@ -1,25 +1,37 @@ import { useQueryClient } from '@tanstack/solid-query'; import { usePreloader } from '../components/common'; -import { getRepo } from './api/repos'; +import { getRepo, type RepoContext } from './api/repos'; import { getIssue } from './api/issues'; -import { getPull } from './api/pulls'; -import { repoQueryKey, issueQueryKey, pullQueryKey } from './api/keys'; +import { fetchPullRoundPatch, getPull } from './api/pulls'; +import { repoQueryKey, issueQueryKey, pullQueryKey, pullPatchQueryKey } from './api/keys'; export const useIssuePreloader = () => { const queryClient = useQueryClient(); const preload = usePreloader(); - return (repoLabel: string, kind: 'issue' | 'pull', uri: string, number?: number) => { + return ( + repoLabel: string, + kind: 'issue' | 'pull', + uri: string, + number?: string | number, + repoContext?: RepoContext, + ) => { const [owner, slug] = repoLabel.split('/'); const issueRef = String(number || uri.split('/').pop()); return preload( [kind, uri, 'prefetch'], async () => { - const repo = await queryClient.fetchQuery({ - queryKey: repoQueryKey(owner, slug), - queryFn: () => getRepo(owner, slug), - }); + const repo = + repoContext || + (await queryClient.fetchQuery({ + queryKey: repoQueryKey(owner, slug), + queryFn: () => getRepo(owner, slug), + })); + + if (!repo) { + return; + } if (kind === 'issue') { await queryClient.prefetchQuery({ @@ -27,10 +39,16 @@ export const useIssuePreloader = () => { queryFn: () => getIssue(repo, issueRef), }); } else { - await queryClient.prefetchQuery({ + const pullDetail = await queryClient.fetchQuery({ queryKey: pullQueryKey(repo.repoDid, issueRef), queryFn: () => getPull(repo, issueRef), }); + + const roundIndex = Math.max(0, pullDetail.pull.value.rounds.length - 1); + await queryClient.prefetchQuery({ + queryKey: pullPatchQueryKey(pullDetail.pull.uri, roundIndex), + queryFn: () => fetchPullRoundPatch(pullDetail.pull, roundIndex), + }); } }, ); diff --git a/src/pages/repo/issues.tsx b/src/pages/repo/issues.tsx index 3d6d5a1..00ac55b 100644 --- a/src/pages/repo/issues.tsx +++ b/src/pages/repo/issues.tsx @@ -9,7 +9,8 @@ import { resolveActor } from '../../lib/api/identity'; import { parseAtUri } from '../../lib/api/records'; import type { RepoContext } from '../../lib/api/repos'; import { useAuth } from '../../lib/auth'; -import { Avatar, ErrorState, PaginationControls, StateBadge, ToggleButton, buttonStyles, cardStyles, inputStyles, textareaStyles, usePreloader } from '../../components/common'; +import { useIssuePreloader } from '../../lib/preloading'; +import { Avatar, ErrorState, PaginationControls, StateBadge, ToggleButton, buttonStyles, cardStyles, inputStyles, textareaStyles } from '../../components/common'; import { AtUriPanel, MarkdownBlock, RepoFormSkeleton, RepoListPageSkeleton, RepoListSkeleton, RepoThreadSkeleton, IssueOrPullRow, ThreadCommentView } from '../../components/repo'; import { RepoFrame, issueQueryKey, issuesQueryKey, useRepoQuery } from './shared'; import { REPO_LIST_PAGE_LIMIT, formatRelativeTime, getErrorMessage, issueHref, parseIntegerSearchParam, uniqueCommenters, saveRecentIssueOrPull } from '../../lib/repo-utils'; @@ -18,6 +19,7 @@ import { buildIssueCommentThreads, buildIssueFilterQuery, parseIssueFilter } fro export const IssuesPage: Component = () => { const auth = useAuth(); const repoQuery = useRepoQuery(); + const issuePreloader = useIssuePreloader(); const [searchParams, setSearchParams] = useSearchParams(); const filter = createMemo(() => parseIssueFilter(searchParams.q)); const stateFilter = createMemo(() => filter().state); @@ -57,8 +59,6 @@ export const IssuesPage: Component = () => { }); }; - const preload = usePreloader(); - const issuesQuery = createQuery(() => { const repo = repoQuery.data; return { @@ -169,7 +169,13 @@ export const IssuesPage: Component = () => { author={{ did: issue.author.did, handle: issue.author.handle }} createdAt={issue.value.createdAt} href={issueHref(repoQuery.data!, issue.number || issue.rkey)} - {...preload(issueQueryKey(repoQuery.data!.repoDid, String(issue.number || issue.rkey)), () => getIssue(repoQuery.data!, String(issue.number || issue.rkey)))} + {...issuePreloader( + `${repoQuery.data!.owner.handle}/${repoQuery.data!.slug}`, + 'issue', + issue.uri, + issue.number || issue.rkey, + repoQuery.data!, + )} /> )} diff --git a/src/pages/repo/pulls.tsx b/src/pages/repo/pulls.tsx index 6f66773..af21a77 100644 --- a/src/pages/repo/pulls.tsx +++ b/src/pages/repo/pulls.tsx @@ -27,15 +27,17 @@ import { createPull, createPullComment, fetchPullRoundPatch, getPull, listPullsP import { parseAtUri } from '../../lib/api/records'; import { compareBranches, getRepoBranches, type RepoContext, compareFork, listRepoRecords } from '../../lib/api/repos'; import { useAuth } from '../../lib/auth'; -import { Avatar, ErrorState, LoadingState, PaginationControls, StateBadge, ToggleButton, buttonStyles, cardStyles, textareaStyles, usePreloader } from '../../components/common'; +import { useIssuePreloader } from '../../lib/preloading'; +import { Avatar, ErrorState, LoadingState, PaginationControls, StateBadge, ToggleButton, buttonStyles, cardStyles, textareaStyles } from '../../components/common'; import { AtUriPanel, BranchPill, DiffView, MarkdownBlock, PullComposeSkeleton, PullDiffSkeleton, PullDiffView, RepoListPageSkeleton, RepoListSkeleton, RepoThreadSkeleton, IssueOrPullRow, ThreadCommentView } from '../../components/repo'; -import { RepoFrame, pullQueryKey, pullsQueryKey, useRepoQuery } from './shared'; +import { RepoFrame, pullQueryKey, pullsQueryKey, useRepoQuery, pullPatchQueryKey } from './shared'; import { REPO_LIST_PAGE_LIMIT, formatRelativeTime, getErrorMessage, parseIntegerSearchParam, pullHref, uniqueCommenters, saveRecentIssueOrPull } from '../../lib/repo-utils'; import { buildPullFilterQuery, parsePastedPatchPrefill, parsePullFilter, type PullSourceMode, getRoundIndexForComment, buildPRCommentThreads } from './pulls-helpers'; export const PullsPage: Component = () => { const auth = useAuth(); const repoQuery = useRepoQuery(); + const issuePreloader = useIssuePreloader(); const [searchParams, setSearchParams] = useSearchParams(); const filter = createMemo(() => parsePullFilter(searchParams.q)); const stateFilter = createMemo(() => filter().state); @@ -75,8 +77,6 @@ export const PullsPage: Component = () => { }); }; - const preload = usePreloader(); - const pullsQuery = createQuery(() => { const repo = repoQuery.data; return { @@ -193,7 +193,13 @@ export const PullsPage: Component = () => { author={{ did: pull.author.did, handle: pull.author.handle }} createdAt={pull.value.createdAt} href={pullHref(repoQuery.data!, pull.number || pull.rkey)} - {...preload(pullQueryKey(repoQuery.data!.repoDid, String(pull.number || pull.rkey)), () => getPull(repoQuery.data!, String(pull.number || pull.rkey)))} + {...issuePreloader( + `${repoQuery.data!.owner.handle}/${repoQuery.data!.slug}`, + 'pull', + pull.uri, + pull.number || pull.rkey, + repoQuery.data!, + )} meta={ <> ยท @@ -1101,7 +1107,7 @@ export const PullPage: Component = () => { const patchQuery = createQuery(() => { const detail = pullQuery.data; return { - queryKey: ['pull-patch', detail?.pull.uri, roundIndex()], + queryKey: pullPatchQueryKey(detail?.pull.uri ?? '', roundIndex()), enabled: Boolean(detail), queryFn: async () => fetchPullRoundPatch(detail!.pull, roundIndex()), }; diff --git a/src/pages/repo/shared.tsx b/src/pages/repo/shared.tsx index 347d39a..d77cc91 100644 --- a/src/pages/repo/shared.tsx +++ b/src/pages/repo/shared.tsx @@ -14,9 +14,9 @@ import { useLiveEvents } from '../../lib/live-events'; import { Avatar, ErrorState, cardStyles } from '../../components/common'; import { RepoFrameSkeleton, RepoTabLink } from '../../components/repo'; import { getErrorMessage, saveRecentRepo, trimUri } from '../../lib/repo-utils'; -import { repoQueryKey, issuesQueryKey, issueQueryKey, pullsQueryKey, pullQueryKey } from '../../lib/api/keys'; +import { repoQueryKey, issuesQueryKey, issueQueryKey, pullsQueryKey, pullQueryKey, pullPatchQueryKey } from '../../lib/api/keys'; -export { repoQueryKey, issuesQueryKey, issueQueryKey, pullsQueryKey, pullQueryKey }; +export { repoQueryKey, issuesQueryKey, issueQueryKey, pullsQueryKey, pullQueryKey, pullPatchQueryKey }; type OptimisticStarState = { state: 'starred'; rkey?: string } | { state: 'unstarred'; rkey: string };