csr tangled client in solid-js
15

Configure Feed

Select the types of activity you want to include in your feed.

preloading for pr diffs

dawn (May 30, 2026, 11:18 PM +0300) 00a96cb1 6293bcce

+52 -21
+1
src/lib/api/keys.ts
··· 3 3 export const issueQueryKey = (repoDid: string, issueRef: string) => ['issue', repoDid, issueRef] as const; 4 4 export const pullsQueryKey = (repoDid: string) => ['pulls', repoDid] as const; 5 5 export const pullQueryKey = (repoDid: string, pullRef: string) => ['pull', repoDid, pullRef] as const; 6 + export const pullPatchQueryKey = (pullUri: string, roundIndex: number) => ['pull-patch', pullUri, roundIndex] as const;
+27 -9
src/lib/preloading.tsx
··· 1 1 import { useQueryClient } from '@tanstack/solid-query'; 2 2 import { usePreloader } from '../components/common'; 3 - import { getRepo } from './api/repos'; 3 + import { getRepo, type RepoContext } from './api/repos'; 4 4 import { getIssue } from './api/issues'; 5 - import { getPull } from './api/pulls'; 6 - import { repoQueryKey, issueQueryKey, pullQueryKey } from './api/keys'; 5 + import { fetchPullRoundPatch, getPull } from './api/pulls'; 6 + import { repoQueryKey, issueQueryKey, pullQueryKey, pullPatchQueryKey } from './api/keys'; 7 7 8 8 export const useIssuePreloader = () => { 9 9 const queryClient = useQueryClient(); 10 10 const preload = usePreloader(); 11 11 12 - return (repoLabel: string, kind: 'issue' | 'pull', uri: string, number?: number) => { 12 + return ( 13 + repoLabel: string, 14 + kind: 'issue' | 'pull', 15 + uri: string, 16 + number?: string | number, 17 + repoContext?: RepoContext, 18 + ) => { 13 19 const [owner, slug] = repoLabel.split('/'); 14 20 const issueRef = String(number || uri.split('/').pop()); 15 21 16 22 return preload( 17 23 [kind, uri, 'prefetch'], 18 24 async () => { 19 - const repo = await queryClient.fetchQuery({ 20 - queryKey: repoQueryKey(owner, slug), 21 - queryFn: () => getRepo(owner, slug), 22 - }); 25 + const repo = 26 + repoContext || 27 + (await queryClient.fetchQuery({ 28 + queryKey: repoQueryKey(owner, slug), 29 + queryFn: () => getRepo(owner, slug), 30 + })); 31 + 32 + if (!repo) { 33 + return; 34 + } 23 35 24 36 if (kind === 'issue') { 25 37 await queryClient.prefetchQuery({ ··· 27 39 queryFn: () => getIssue(repo, issueRef), 28 40 }); 29 41 } else { 30 - await queryClient.prefetchQuery({ 42 + const pullDetail = await queryClient.fetchQuery({ 31 43 queryKey: pullQueryKey(repo.repoDid, issueRef), 32 44 queryFn: () => getPull(repo, issueRef), 45 + }); 46 + 47 + const roundIndex = Math.max(0, pullDetail.pull.value.rounds.length - 1); 48 + await queryClient.prefetchQuery({ 49 + queryKey: pullPatchQueryKey(pullDetail.pull.uri, roundIndex), 50 + queryFn: () => fetchPullRoundPatch(pullDetail.pull, roundIndex), 33 51 }); 34 52 } 35 53 },
+10 -4
src/pages/repo/issues.tsx
··· 9 9 import { parseAtUri } from '../../lib/api/records'; 10 10 import type { RepoContext } from '../../lib/api/repos'; 11 11 import { useAuth } from '../../lib/auth'; 12 - import { Avatar, ErrorState, PaginationControls, StateBadge, ToggleButton, buttonStyles, cardStyles, inputStyles, textareaStyles, usePreloader } from '../../components/common'; 12 + import { useIssuePreloader } from '../../lib/preloading'; 13 + import { Avatar, ErrorState, PaginationControls, StateBadge, ToggleButton, buttonStyles, cardStyles, inputStyles, textareaStyles } from '../../components/common'; 13 14 import { AtUriPanel, MarkdownBlock, RepoFormSkeleton, RepoListPageSkeleton, RepoListSkeleton, RepoThreadSkeleton, IssueOrPullRow, ThreadCommentView } from '../../components/repo'; 14 15 import { RepoFrame, issueQueryKey, issuesQueryKey, useRepoQuery } from './shared'; 15 16 import { REPO_LIST_PAGE_LIMIT, formatRelativeTime, getErrorMessage, issueHref, parseIntegerSearchParam, uniqueCommenters, saveRecentIssueOrPull } from '../../lib/repo-utils'; ··· 18 19 export const IssuesPage: Component = () => { 19 20 const auth = useAuth(); 20 21 const repoQuery = useRepoQuery(); 22 + const issuePreloader = useIssuePreloader(); 21 23 const [searchParams, setSearchParams] = useSearchParams(); 22 24 const filter = createMemo(() => parseIssueFilter(searchParams.q)); 23 25 const stateFilter = createMemo(() => filter().state); ··· 56 58 limit: String(pageLimit()), 57 59 }); 58 60 }; 59 - 60 - const preload = usePreloader(); 61 61 62 62 const issuesQuery = createQuery(() => { 63 63 const repo = repoQuery.data; ··· 169 169 author={{ did: issue.author.did, handle: issue.author.handle }} 170 170 createdAt={issue.value.createdAt} 171 171 href={issueHref(repoQuery.data!, issue.number || issue.rkey)} 172 - {...preload(issueQueryKey(repoQuery.data!.repoDid, String(issue.number || issue.rkey)), () => getIssue(repoQuery.data!, String(issue.number || issue.rkey)))} 172 + {...issuePreloader( 173 + `${repoQuery.data!.owner.handle}/${repoQuery.data!.slug}`, 174 + 'issue', 175 + issue.uri, 176 + issue.number || issue.rkey, 177 + repoQuery.data!, 178 + )} 173 179 /> 174 180 )} 175 181 </For>
+12 -6
src/pages/repo/pulls.tsx
··· 27 27 import { parseAtUri } from '../../lib/api/records'; 28 28 import { compareBranches, getRepoBranches, type RepoContext, compareFork, listRepoRecords } from '../../lib/api/repos'; 29 29 import { useAuth } from '../../lib/auth'; 30 - import { Avatar, ErrorState, LoadingState, PaginationControls, StateBadge, ToggleButton, buttonStyles, cardStyles, textareaStyles, usePreloader } from '../../components/common'; 30 + import { useIssuePreloader } from '../../lib/preloading'; 31 + import { Avatar, ErrorState, LoadingState, PaginationControls, StateBadge, ToggleButton, buttonStyles, cardStyles, textareaStyles } from '../../components/common'; 31 32 import { AtUriPanel, BranchPill, DiffView, MarkdownBlock, PullComposeSkeleton, PullDiffSkeleton, PullDiffView, RepoListPageSkeleton, RepoListSkeleton, RepoThreadSkeleton, IssueOrPullRow, ThreadCommentView } from '../../components/repo'; 32 - import { RepoFrame, pullQueryKey, pullsQueryKey, useRepoQuery } from './shared'; 33 + import { RepoFrame, pullQueryKey, pullsQueryKey, useRepoQuery, pullPatchQueryKey } from './shared'; 33 34 import { REPO_LIST_PAGE_LIMIT, formatRelativeTime, getErrorMessage, parseIntegerSearchParam, pullHref, uniqueCommenters, saveRecentIssueOrPull } from '../../lib/repo-utils'; 34 35 import { buildPullFilterQuery, parsePastedPatchPrefill, parsePullFilter, type PullSourceMode, getRoundIndexForComment, buildPRCommentThreads } from './pulls-helpers'; 35 36 36 37 export const PullsPage: Component = () => { 37 38 const auth = useAuth(); 38 39 const repoQuery = useRepoQuery(); 40 + const issuePreloader = useIssuePreloader(); 39 41 const [searchParams, setSearchParams] = useSearchParams(); 40 42 const filter = createMemo(() => parsePullFilter(searchParams.q)); 41 43 const stateFilter = createMemo(() => filter().state); ··· 74 76 limit: String(pageLimit()), 75 77 }); 76 78 }; 77 - 78 - const preload = usePreloader(); 79 79 80 80 const pullsQuery = createQuery(() => { 81 81 const repo = repoQuery.data; ··· 193 193 author={{ did: pull.author.did, handle: pull.author.handle }} 194 194 createdAt={pull.value.createdAt} 195 195 href={pullHref(repoQuery.data!, pull.number || pull.rkey)} 196 - {...preload(pullQueryKey(repoQuery.data!.repoDid, String(pull.number || pull.rkey)), () => getPull(repoQuery.data!, String(pull.number || pull.rkey)))} 196 + {...issuePreloader( 197 + `${repoQuery.data!.owner.handle}/${repoQuery.data!.slug}`, 198 + 'pull', 199 + pull.uri, 200 + pull.number || pull.rkey, 201 + repoQuery.data!, 202 + )} 197 203 meta={ 198 204 <> 199 205 <span>·</span> ··· 1101 1107 const patchQuery = createQuery(() => { 1102 1108 const detail = pullQuery.data; 1103 1109 return { 1104 - queryKey: ['pull-patch', detail?.pull.uri, roundIndex()], 1110 + queryKey: pullPatchQueryKey(detail?.pull.uri ?? '', roundIndex()), 1105 1111 enabled: Boolean(detail), 1106 1112 queryFn: async () => fetchPullRoundPatch(detail!.pull, roundIndex()), 1107 1113 };
+2 -2
src/pages/repo/shared.tsx
··· 14 14 import { Avatar, ErrorState, cardStyles } from '../../components/common'; 15 15 import { RepoFrameSkeleton, RepoTabLink } from '../../components/repo'; 16 16 import { getErrorMessage, saveRecentRepo, trimUri } from '../../lib/repo-utils'; 17 - import { repoQueryKey, issuesQueryKey, issueQueryKey, pullsQueryKey, pullQueryKey } from '../../lib/api/keys'; 17 + import { repoQueryKey, issuesQueryKey, issueQueryKey, pullsQueryKey, pullQueryKey, pullPatchQueryKey } from '../../lib/api/keys'; 18 18 19 - export { repoQueryKey, issuesQueryKey, issueQueryKey, pullsQueryKey, pullQueryKey }; 19 + export { repoQueryKey, issuesQueryKey, issueQueryKey, pullsQueryKey, pullQueryKey, pullPatchQueryKey }; 20 20 21 21 type OptimisticStarState = { state: 'starred'; rkey?: string } | { state: 'unstarred'; rkey: string }; 22 22