diff --git a/src/components/repo/IssueComments.tsx b/src/components/repo/IssueComments.tsx index f54d81d..4f6d82e 100644 --- a/src/components/repo/IssueComments.tsx +++ b/src/components/repo/IssueComments.tsx @@ -13,11 +13,12 @@ import { SurfaceCard } from '../shared/SurfaceCard' const COMMENT_SKELETON_COUNT = 3 type IssueCommentsProps = { + isActive?: boolean issueUri: CommentRecord['value']['subject']['uri'] } -export function IssueComments({ issueUri }: IssueCommentsProps) { - const { comments, error, hasMore, isLoadingMore, loadMore } = useIssueComments(issueUri) +export function IssueComments({ isActive = true, issueUri }: IssueCommentsProps) { + const { comments, error, hasMore, isLoadingMore, loadMore } = useIssueComments(issueUri, isActive) if (error && comments === null) { return

Could not load comments: {error.message}

diff --git a/src/components/repo/PullChanges.tsx b/src/components/repo/PullChanges.tsx index 8e783d8..863fce4 100644 --- a/src/components/repo/PullChanges.tsx +++ b/src/components/repo/PullChanges.tsx @@ -1,19 +1,27 @@ import type { Blob, Did, LegacyBlob } from '@atcute/lexicons' import type { Main as Pull } from '@atcute/tangled/types/repo/pull' +import { useCallback } from 'react' import { useDeferredResource } from '../../hooks/useDeferredResource' import { SurfaceCard } from '../shared/SurfaceCard' type PullChangesProps = { + isActive: boolean pull: Pull pullAuthorDid: Did pullAuthorPds: string } -export function PullChanges({ pull, pullAuthorDid, pullAuthorPds }: PullChangesProps) { +export function PullChanges({ isActive, pull, pullAuthorDid, pullAuthorPds }: PullChangesProps) { const latestRound = pull.rounds.at(-1) const patchCid = latestRound === undefined ? null : getBlobCid(latestRound.patchBlob) - const { data: patch, error } = useDeferredResource(patchCid, latestRound !== undefined, () => - loadPatch(pullAuthorPds, pullAuthorDid, patchCid), + const loadLatestPatch = useCallback( + () => loadPatch(pullAuthorPds, pullAuthorDid, patchCid), + [patchCid, pullAuthorDid, pullAuthorPds], + ) + const { data: patch, error } = useDeferredResource( + isActive ? patchCid : null, + isActive && latestRound !== undefined, + loadLatestPatch, ) if (latestRound === undefined) { diff --git a/src/components/repo/RepoIssues.tsx b/src/components/repo/RepoIssues.tsx index 519c005..398a4b8 100644 --- a/src/components/repo/RepoIssues.tsx +++ b/src/components/repo/RepoIssues.tsx @@ -9,13 +9,14 @@ import { SurfaceCard } from '../shared/SurfaceCard' import { LoadMoreButton } from '../shared/LoadMoreButton' type RepoIssuesProps = { + isActive: boolean repoOwnerHandle: Handle repoDid: Did repoKey: string } -export function RepoIssues({ repoOwnerHandle, repoDid, repoKey }: RepoIssuesProps) { - const { issues, error, hasMore, isLoadingMore, loadMore } = useRepoIssues(repoDid) +export function RepoIssues({ isActive, repoOwnerHandle, repoDid, repoKey }: RepoIssuesProps) { + const { issues, error, hasMore, isLoadingMore, loadMore } = useRepoIssues(repoDid, isActive) if (error && issues === null) { return

Could not load issues: {error.message}

diff --git a/src/components/repo/RepoLog.tsx b/src/components/repo/RepoLog.tsx index 05734a2..759b46d 100644 --- a/src/components/repo/RepoLog.tsx +++ b/src/components/repo/RepoLog.tsx @@ -6,11 +6,12 @@ import { WorkspacePaneHeader } from './WorkspacePaneHeader' type RepoLogProps = { branch?: string + isActive: boolean repo: Repo } -export function RepoLog({ branch, repo }: RepoLogProps) { - const { commits, error } = useRepoCommits(repo, branch) +export function RepoLog({ branch, isActive, repo }: RepoLogProps) { + const { commits, error } = useRepoCommits(repo, branch, isActive) if (error) { return

Could not load commits: {error.message}

diff --git a/src/components/repo/RepoPipelines.tsx b/src/components/repo/RepoPipelines.tsx index c0479a2..495ffd1 100644 --- a/src/components/repo/RepoPipelines.tsx +++ b/src/components/repo/RepoPipelines.tsx @@ -5,7 +5,15 @@ import type { Main as Pipeline } from '@atcute/tangled/types/ci/pipeline' import { LoadMoreButton } from '../shared/LoadMoreButton' import { SurfaceCard } from '../shared/SurfaceCard' -export function RepoPipelines({ repoDid, spindle }: { repoDid: Did; spindle?: string }) { +export function RepoPipelines({ + isActive, + repoDid, + spindle, +}: { + isActive: boolean + repoDid: Did + spindle?: string +}) { if (spindle === undefined) return (

@@ -13,11 +21,23 @@ export function RepoPipelines({ repoDid, spindle }: { repoDid: Did; spindle?: st

) - return + return } -function ConfiguredRepoPipelines({ repoDid, spindle }: { repoDid: Did; spindle: string }) { - const { pipelines, error, hasMore, isLoadingMore, loadMore } = useRepoPipelines(repoDid, spindle) +function ConfiguredRepoPipelines({ + isActive, + repoDid, + spindle, +}: { + isActive: boolean + repoDid: Did + spindle: string +}) { + const { pipelines, error, hasMore, isLoadingMore, loadMore } = useRepoPipelines( + repoDid, + spindle, + isActive, + ) if (error && pipelines === null) return

Could not load pipelines: {error.message}

diff --git a/src/components/repo/RepoPulls.tsx b/src/components/repo/RepoPulls.tsx index 8e8f3ea..ca5ec0b 100644 --- a/src/components/repo/RepoPulls.tsx +++ b/src/components/repo/RepoPulls.tsx @@ -9,13 +9,14 @@ import { SurfaceCard } from '../shared/SurfaceCard' import { LoadMoreButton } from '../shared/LoadMoreButton' type RepoPullsProps = { + isActive: boolean repoOwnerHandle: Handle repoDid: Did repoKey: string } -export function RepoPulls({ repoOwnerHandle, repoDid, repoKey }: RepoPullsProps) { - const { pulls, error, hasMore, isLoadingMore, loadMore } = useRepoPulls(repoDid) +export function RepoPulls({ isActive, repoOwnerHandle, repoDid, repoKey }: RepoPullsProps) { + const { pulls, error, hasMore, isLoadingMore, loadMore } = useRepoPulls(repoDid, isActive) if (error && pulls === null) { return

Could not load pulls: {error.message}

diff --git a/src/components/repo/RepoTree.tsx b/src/components/repo/RepoTree.tsx index 79c848c..97e600f 100644 --- a/src/components/repo/RepoTree.tsx +++ b/src/components/repo/RepoTree.tsx @@ -12,14 +12,15 @@ import { getParentPath, sortTreeEntries } from './repoTreeUtils' type RepoTreeProps = { initialTree?: RepoTreeResponse + isActive: boolean repo: Repo } -export function RepoTree({ initialTree, repo }: RepoTreeProps) { +export function RepoTree({ initialTree, isActive, repo }: RepoTreeProps) { const [searchParams, setSearchParams] = useSearchParams() const path = searchParams.get('path') ?? '' const repoName = getRepoName(repo) - const { error, tree } = useRepoTree({ initialTree, path, repo }) + const { error, tree } = useRepoTree({ initialTree, isEnabled: isActive, path, repo }) function navigateToPath(nextPath: string) { setSearchParams( diff --git a/src/components/repo/RepoWorkspace.tsx b/src/components/repo/RepoWorkspace.tsx index 7afcfe8..d89c404 100644 --- a/src/components/repo/RepoWorkspace.tsx +++ b/src/components/repo/RepoWorkspace.tsx @@ -5,17 +5,18 @@ import { RepoTree } from './RepoTree' type RepoWorkspaceProps = { initialTree?: RepoTreeResponse + isActive: boolean repo: Repo } -export function RepoWorkspace({ initialTree, repo }: RepoWorkspaceProps) { +export function RepoWorkspace({ initialTree, isActive, repo }: RepoWorkspaceProps) { return (
- +
- +
) diff --git a/src/hooks/useDeferredResource.ts b/src/hooks/useDeferredResource.ts index 243ee6e..d8d28f9 100644 --- a/src/hooks/useDeferredResource.ts +++ b/src/hooks/useDeferredResource.ts @@ -1,9 +1,5 @@ import { useEffect, useRef, useState } from 'react' -type DeferredResourceOptions = { - cache?: boolean -} - type ResourceState = { data?: T error?: Error @@ -14,20 +10,15 @@ export function useDeferredResource( key: string | null, isEnabled: boolean, load: (key: string) => Promise, - { cache = false }: DeferredResourceOptions = {}, ) { - const cachedValues = useRef(new Map()) const inFlightRequests = useRef(new Map>()) const [state, setState] = useState | null>(null) + const stateRef = useRef(state) + stateRef.current = state useEffect(() => { if (key === null || !isEnabled) return - - const cachedValue = cache ? cachedValues.current.get(key) : undefined - if (cachedValue !== undefined) { - setState({ key, data: cachedValue }) - return - } + if (stateRef.current?.key === key && stateRef.current.data !== undefined) return let isCancelled = false setState({ key }) @@ -35,7 +26,6 @@ export function useDeferredResource( const request = getRequest(key, load, inFlightRequests.current) void request .then((data) => { - if (cache) cachedValues.current.set(key, data) if (!isCancelled) setState({ key, data }) }) .catch((caught) => { @@ -50,7 +40,7 @@ export function useDeferredResource( return () => { isCancelled = true } - }, [cache, isEnabled, key, load]) + }, [isEnabled, key, load]) const isCurrentResource = state?.key === key return { diff --git a/src/hooks/useIssueComments.ts b/src/hooks/useIssueComments.ts index d661f48..3d49270 100644 --- a/src/hooks/useIssueComments.ts +++ b/src/hooks/useIssueComments.ts @@ -4,9 +4,9 @@ import { useCursorList } from './useCursorList' const INITIAL_COMMENT_LIMIT = 20 -export function useIssueComments(issue: ResourceUri) { +export function useIssueComments(issue: ResourceUri, isEnabled = true) { const { data, error, hasMore, isLoadingMore, loadMore } = useCursorList( - issue, + isEnabled ? issue : null, (options) => listComments(issue, { ...options, order: 'asc' }), INITIAL_COMMENT_LIMIT, ) diff --git a/src/hooks/useProfileSections.ts b/src/hooks/useProfileSections.ts index 54f5dde..37faf57 100644 --- a/src/hooks/useProfileSections.ts +++ b/src/hooks/useProfileSections.ts @@ -35,7 +35,7 @@ export function useProfileVouches(did: Did, isEnabled: boolean) { } export function usePinnedRepos(repoDids: readonly Did[], isEnabled: boolean) { - return useDeferredResource(repoDids.join(','), isEnabled, loadPinnedRepos, { cache: true }) + return useDeferredResource(repoDids.join(','), isEnabled, loadPinnedRepos) } export function useStarredRepos(did: Did, isEnabled: boolean) { diff --git a/src/hooks/useRepoCommits.ts b/src/hooks/useRepoCommits.ts index a22a3b8..d8f73ed 100644 --- a/src/hooks/useRepoCommits.ts +++ b/src/hooks/useRepoCommits.ts @@ -3,13 +3,13 @@ import type { Repo } from '../lib/tangled' import { getRecentCommits, type RepoCommit } from '../lib/tangled/repo' import { useDeferredResource } from './useDeferredResource' -export function useRepoCommits(repo: Repo, branch?: string) { +export function useRepoCommits(repo: Repo, branch: string | undefined, isEnabled: boolean) { const loadCommits = useCallback( (): Promise => getRecentCommits(repo, { branch }), [branch, repo], ) - const key = `${repo.uri}:${branch ?? 'default'}` - const { data: commits, error } = useDeferredResource(key, true, loadCommits) + const key = isEnabled ? `${repo.uri}:${branch ?? 'default'}` : null + const { data: commits, error } = useDeferredResource(key, isEnabled, loadCommits) return { commits, error } } diff --git a/src/hooks/useRepoIssues.ts b/src/hooks/useRepoIssues.ts index 1438df9..57565c0 100644 --- a/src/hooks/useRepoIssues.ts +++ b/src/hooks/useRepoIssues.ts @@ -4,9 +4,9 @@ import { useCursorList } from './useCursorList' const INITIAL_ISSUE_LIMIT = 20 -export function useRepoIssues(repoDid: Did) { +export function useRepoIssues(repoDid: Did, isEnabled: boolean) { const { data, error, hasMore, isLoadingMore, loadMore } = useCursorList( - repoDid, + isEnabled ? repoDid : null, (options) => listIssues(repoDid, options), INITIAL_ISSUE_LIMIT, ) diff --git a/src/hooks/useRepoPipelines.ts b/src/hooks/useRepoPipelines.ts index ac63fcd..616e2d2 100644 --- a/src/hooks/useRepoPipelines.ts +++ b/src/hooks/useRepoPipelines.ts @@ -4,9 +4,9 @@ import { useCursorList } from './useCursorList' const INITIAL_PIPELINE_LIMIT = 20 -export function useRepoPipelines(repoDid: Did, spindle: string) { +export function useRepoPipelines(repoDid: Did, spindle: string, isEnabled: boolean) { const result = useCursorList( - `${spindle}:${repoDid}`, + isEnabled ? `${spindle}:${repoDid}` : null, (options) => queryPipelines(spindle, repoDid, options), INITIAL_PIPELINE_LIMIT, ) diff --git a/src/hooks/useRepoPulls.ts b/src/hooks/useRepoPulls.ts index df79ca7..aaaba53 100644 --- a/src/hooks/useRepoPulls.ts +++ b/src/hooks/useRepoPulls.ts @@ -4,9 +4,9 @@ import { useCursorList } from './useCursorList' const INITIAL_PULL_LIMIT = 20 -export function useRepoPulls(repoDid: Did) { +export function useRepoPulls(repoDid: Did, isEnabled: boolean) { const { data, error, hasMore, isLoadingMore, loadMore } = useCursorList( - repoDid, + isEnabled ? repoDid : null, (options) => listPulls(repoDid, options), INITIAL_PULL_LIMIT, ) diff --git a/src/hooks/useRepoRootTree.ts b/src/hooks/useRepoRootTree.ts index e201efc..ca36b88 100644 --- a/src/hooks/useRepoRootTree.ts +++ b/src/hooks/useRepoRootTree.ts @@ -9,9 +9,7 @@ export function useRepoRootTree(repo: Repo | null, isEnabled: boolean) { return getRepoTree(repo) }, [repo]) - const { data, error } = useDeferredResource(repo?.uri ?? null, isEnabled, loadRootTree, { - cache: true, - }) + const { data, error } = useDeferredResource(repo?.uri ?? null, isEnabled, loadRootTree) return { error, rootTree: data } } diff --git a/src/hooks/useRepoTree.ts b/src/hooks/useRepoTree.ts index 894ad28..d960450 100644 --- a/src/hooks/useRepoTree.ts +++ b/src/hooks/useRepoTree.ts @@ -5,11 +5,12 @@ import { getRepoTree } from '../lib/tangled/repo' type UseRepoTreeOptions = { initialTree?: RepoTreeResponse + isEnabled: boolean path: string repo: Repo } -export function useRepoTree({ initialTree, path, repo }: UseRepoTreeOptions) { +export function useRepoTree({ initialTree, isEnabled, path, repo }: UseRepoTreeOptions) { const cache = useRef(new Map()) const [tree, setTree] = useState(initialTree ?? null) const [error, setError] = useState(null) @@ -26,6 +27,8 @@ export function useRepoTree({ initialTree, path, repo }: UseRepoTreeOptions) { }, [initialTree, repo.uri]) useEffect(() => { + if (!isEnabled) return + let isCancelled = false const cachedTree = cache.current.get(path) @@ -58,7 +61,7 @@ export function useRepoTree({ initialTree, path, repo }: UseRepoTreeOptions) { return () => { isCancelled = true } - }, [initialTree?.ref, path, repo]) + }, [initialTree?.ref, isEnabled, path, repo]) return { error, tree } } diff --git a/src/pages/PullPage.tsx b/src/pages/PullPage.tsx index 1cb9e60..5b9c9e7 100644 --- a/src/pages/PullPage.tsx +++ b/src/pages/PullPage.tsx @@ -91,14 +91,17 @@ export function PullPage() { }, ]} /> - {activeTab === 'conversation' && } - {activeTab === 'changes' && ( + + diff --git a/src/pages/RepoPage.tsx b/src/pages/RepoPage.tsx index 2aabcda..c498c99 100644 --- a/src/pages/RepoPage.tsx +++ b/src/pages/RepoPage.tsx @@ -76,16 +76,24 @@ export function RepoPage() { repoKey={getRepoRkey(repo)} /> - {activeSection === 'readme' && rootTree !== null && ( - + {rootTree !== null && ( + )} - {activeSection === 'code' && rootTree !== null && ( - + {rootTree !== null && ( + )} {shouldShowContentLoading && ( @@ -93,22 +101,34 @@ export function RepoPage() { {shouldShowContentError && rootTreeError !== null && (

Could not load repository contents: {rootTreeError.message}

)} - {activeSection === 'issues' && repo.value.repoDid !== undefined && ( - + {repo.value.repoDid !== undefined && ( + )} - {activeSection === 'pulls' && repo.value.repoDid !== undefined && ( - + {repo.value.repoDid !== undefined && ( + )} - {activeSection === 'pipelines' && repo.value.repoDid !== undefined && ( - + {repo.value.repoDid !== undefined && ( + )}