Skip to content

Commit 315a43e

Browse files
committed
Use refreshing state to show loading
while project cache is refreshed
1 parent ff9d727 commit 315a43e

File tree

4 files changed

+23
-28
lines changed

4 files changed

+23
-28
lines changed

src/app/(authed)/(project-doc)/[...slug]/layout.tsx

Lines changed: 7 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -4,32 +4,21 @@ import { Box, Stack } from "@mui/material"
44
import { useTheme } from "@mui/material/styles"
55
import TrailingToolbarItem from "@/features/projects/view/toolbar/TrailingToolbarItem"
66
import MobileToolbar from "@/features/projects/view/toolbar/MobileToolbar"
7-
import SecondaryHeaderPlaceholder from "@/features/sidebar/view/SecondarySplitHeaderPlaceholder"
8-
import { useContext } from "react"
9-
import { ProjectsContext } from "@/common"
10-
import LoadingIndicator from "@/common/ui/LoadingIndicator"
117
import SecondarySplitHeader from "@/features/sidebar/view/SecondarySplitHeader"
128

139
export default function Page({ children }: { children: React.ReactNode }) {
14-
const { refreshed } = useContext(ProjectsContext)
15-
1610
const theme = useTheme()
1711

1812
return (
1913
<Stack sx={{ height: "100%" }}>
2014
<>
21-
{!refreshed ? <SecondaryHeaderPlaceholder/> :
22-
<SecondarySplitHeader mobileToolbar={<MobileToolbar/>}>
23-
<TrailingToolbarItem/>
24-
</SecondarySplitHeader>
25-
}
26-
<Box sx={{ height: "0.5px", background: theme.palette.divider }} />
27-
{refreshed ?
28-
<main style={{ flexGrow: "1", overflowY: "auto" }}>
29-
{children}
30-
</main> :
31-
<LoadingIndicator />
32-
}
15+
<SecondarySplitHeader mobileToolbar={<MobileToolbar/>}>
16+
<TrailingToolbarItem/>
17+
</SecondarySplitHeader>
18+
<Box sx={{ height: "0.5px", background: theme.palette.divider }} />
19+
<main style={{ flexGrow: "1", overflowY: "auto" }}>
20+
{children}
21+
</main>
3322
</>
3423
</Stack>
3524
)

src/app/(authed)/(project-doc)/[...slug]/page.tsx

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,17 @@
11
"use client"
22

3-
import { useEffect } from "react"
3+
import { useContext, useEffect } from "react"
44
import ErrorMessage from "@/common/ui/ErrorMessage"
55
import { updateWindowTitle } from "@/features/projects/domain"
66
import { useProjectSelection } from "@/features/projects/data"
77
import Documentation from "@/features/projects/view/Documentation"
88
import NotFound from "@/features/projects/view/NotFound"
9+
import { ProjectsContext } from "@/common/context/ProjectsContext"
10+
import LoadingIndicator from "@/common/ui/LoadingIndicator"
911

1012
export default function Page() {
1113
const { project, version, specification, navigateToSelectionIfNeeded } = useProjectSelection()
14+
const { refreshing } = useContext(ProjectsContext)
1215
// Ensure the URL reflects the current selection of project, version, and specification.
1316
useEffect(() => {
1417
navigateToSelectionIfNeeded()
@@ -30,10 +33,13 @@ export default function Page() {
3033
{project && version && specification &&
3134
<Documentation url={specification.url} />
3235
}
33-
{project && (!version || !specification) &&
36+
{project && (!version || !specification) && !refreshing &&
3437
<ErrorMessage text={`The selected ${!version ? "branch or tag" : "specification"} was not found.`}/>
3538
}
36-
{!project && <NotFound/>}
39+
{refreshing && // project data is currently being fetched - show loading indicator
40+
<LoadingIndicator />
41+
}
42+
{!project && !refreshing && <NotFound/>}
3743
</>
3844
)
3945
}

src/common/context/ProjectsContext.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,13 @@ import { Project } from "@/features/projects/domain"
66
export const SidebarTogglableContext = createContext<boolean>(true)
77

88
type ProjectsContextValue = {
9-
refreshed: boolean,
9+
refreshing: boolean,
1010
projects: Project[],
1111
setProjects: (projects: Project[]) => void
1212
}
1313

1414
export const ProjectsContext = createContext<ProjectsContextValue>({
15-
refreshed: false,
15+
refreshing: false,
1616
projects: [],
1717
setProjects: () => {}
1818
})

src/features/projects/view/ProjectsContextProvider.tsx

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,9 @@ const ProjectsContextProvider = ({
1111
initialProjects?: Project[];
1212
children?: React.ReactNode;
1313
}) => {
14-
const [refreshed, setRefreshed] = useState<boolean>(true);
1514
const [projects, setProjects] = useState<Project[]>(initialProjects || []);
1615
const isLoadingRef = useRef(false);
16+
const [refreshing, setRefreshing] = useState(false);
1717

1818
const hasProjectChanged = (value: Project[]) =>
1919
value.some((project, index) => {
@@ -26,16 +26,15 @@ const ProjectsContextProvider = ({
2626

2727
const setProjectsAndRefreshed = (value: Project[]) => {
2828
setProjects(value);
29-
// If any project has changed, update the state and mark as refreshed
30-
if (hasProjectChanged(value)) setRefreshed(true);
3129
};
3230

3331
// Trigger background refresh after initial mount
3432
useEffect(() => {
3533
const refreshProjects = () => {
3634
if (isLoadingRef.current) return;
3735
isLoadingRef.current = true;
38-
36+
setRefreshing(true);
37+
3938
fetch("/api/projects", { method: "POST" })
4039
.then((res) => res.json())
4140
.then(
@@ -47,6 +46,7 @@ const ProjectsContextProvider = ({
4746
.catch((error) => console.error("Failed to refresh projects", error))
4847
.finally(() => {
4948
isLoadingRef.current = false;
49+
setRefreshing(false);
5050
});
5151
};
5252
// Initial refresh
@@ -65,8 +65,8 @@ const ProjectsContextProvider = ({
6565
return (
6666
<ProjectsContext.Provider
6767
value={{
68-
refreshed,
6968
projects,
69+
refreshing,
7070
setProjects: setProjectsAndRefreshed,
7171
}}
7272
>

0 commit comments

Comments
 (0)