|
1 | | -import { memo, Suspense, useEffect, useMemo, useRef, useState } from "react"; |
2 | 1 | import "./PaginatedDependencies.css"; |
3 | 2 | import { Heading, NewPagination, SkeletonBox } from "@thunderstore/cyberstorm"; |
4 | 3 | import { ListingDependency } from "../ListingDependency/ListingDependency"; |
5 | | -import { Await, useNavigationType, useSearchParams } from "react-router"; |
6 | | -import { useDebounce } from "use-debounce"; |
7 | | -import type { getPackageVersionDetails } from "@thunderstore/dapper-ts/src/methods/packageVersion"; |
8 | | -import type { getPackageVersionDependencies } from "@thunderstore/dapper-ts/src/methods/package"; |
9 | | -import { setParamsBlobValue } from "cyberstorm/utils/searchParamsUtils"; |
| 4 | +import { useSearchParams } from "react-router"; |
10 | 5 |
|
11 | 6 | interface Props { |
12 | | - version: |
13 | | - | Awaited<ReturnType<typeof getPackageVersionDetails>> |
14 | | - | ReturnType<typeof getPackageVersionDetails>; |
15 | | - dependencies: |
16 | | - | Awaited<ReturnType<typeof getPackageVersionDependencies>> |
17 | | - | ReturnType<typeof getPackageVersionDependencies>; |
| 7 | + version: any; // Replace 'any' with the appropriate type for version |
| 8 | + dependencies: any; // Replace 'any' with the appropriate type for dependencies |
18 | 9 | pageSize?: number; |
19 | 10 | siblingCount?: number; |
20 | 11 | } |
21 | 12 |
|
22 | | -export const PaginatedDependencies = memo(function PaginatedDependencies( |
23 | | - props: Props |
24 | | -) { |
25 | | - const navigationType = useNavigationType(); |
26 | | - |
| 13 | +export function PaginatedDependencies({ |
| 14 | + version, |
| 15 | + dependencies, |
| 16 | + pageSize = 20, // Default page size from backend |
| 17 | + siblingCount = 4, |
| 18 | +}: Props) { |
27 | 19 | const [searchParams, setSearchParams] = useSearchParams(); |
| 20 | + const page = Number(searchParams.get("page") ?? 1); |
28 | 21 |
|
29 | | - const initialParams = searchParamsToBlob(searchParams); |
30 | | - |
31 | | - const [searchParamsBlob, setSearchParamsBlob] = |
32 | | - useState<SearchParamsType>(initialParams); |
33 | | - |
34 | | - const [currentPage, setCurrentPage] = useState( |
35 | | - searchParams.get("page") ? Number(searchParams.get("page")) : 1 |
36 | | - ); |
37 | | - |
38 | | - const [debouncedSearchParamsBlob] = useDebounce(searchParamsBlob, 300, { |
39 | | - maxWait: 300, |
40 | | - }); |
41 | | - |
42 | | - const searchParamsBlobRef = useRef(debouncedSearchParamsBlob); |
43 | | - |
44 | | - const searchParamsRef = useRef(searchParams); |
45 | | - useEffect(() => { |
46 | | - if (navigationType === "POP") { |
47 | | - if (searchParamsRef.current !== searchParams) { |
48 | | - const spb = searchParamsToBlob(searchParams); |
49 | | - setSearchParamsBlob(spb); |
50 | | - setCurrentPage(spb.page); |
51 | | - searchParamsRef.current = searchParams; |
52 | | - } |
53 | | - searchParamsBlobRef.current = searchParamsToBlob(searchParams); |
54 | | - } |
55 | | - }, [searchParams]); |
56 | | - |
57 | | - useEffect(() => { |
58 | | - if ( |
59 | | - navigationType !== "POP" || |
60 | | - (navigationType === "POP" && |
61 | | - searchParamsBlobRef.current !== debouncedSearchParamsBlob) |
62 | | - ) { |
63 | | - if (searchParamsBlobRef.current !== debouncedSearchParamsBlob) { |
64 | | - const oldPage = searchParams.get("page") |
65 | | - ? Number(searchParams.get("page")) |
66 | | - : 1; |
67 | | - // Page number |
68 | | - if (oldPage !== debouncedSearchParamsBlob.page) { |
69 | | - if (debouncedSearchParamsBlob.page === 1) { |
70 | | - searchParams.delete("page"); |
71 | | - setCurrentPage(1); |
72 | | - } else { |
73 | | - searchParams.set("page", String(debouncedSearchParamsBlob.page)); |
74 | | - setCurrentPage(debouncedSearchParamsBlob.page); |
75 | | - } |
76 | | - } |
77 | | - const uncommittedSearchParams = searchParamsToBlob(searchParams); |
78 | | - |
79 | | - if ( |
80 | | - navigationType !== "POP" || |
81 | | - (navigationType === "POP" && |
82 | | - !compareSearchParamBlobs( |
83 | | - uncommittedSearchParams, |
84 | | - searchParamsBlobRef.current |
85 | | - ) && |
86 | | - compareSearchParamBlobs( |
87 | | - uncommittedSearchParams, |
88 | | - debouncedSearchParamsBlob |
89 | | - )) |
90 | | - ) { |
91 | | - setSearchParams(searchParams, { preventScrollReset: true }); |
92 | | - } |
93 | | - searchParamsBlobRef.current = debouncedSearchParamsBlob; |
94 | | - } |
95 | | - } |
96 | | - }, [debouncedSearchParamsBlob]); |
97 | | - |
98 | | - const versionAndDependencies = useMemo( |
99 | | - () => Promise.all([props.version, props.dependencies]), |
100 | | - [currentPage] |
101 | | - ); |
| 22 | + const handlePageChange = (nextPage: number) => { |
| 23 | + const next = new URLSearchParams(searchParams); |
| 24 | + nextPage === 1 ? next.delete("page") : next.set("page", String(nextPage)); |
| 25 | + setSearchParams(next, { preventScrollReset: true }); |
| 26 | + }; |
102 | 27 |
|
103 | 28 | return ( |
104 | 29 | <div className="paginated-dependencies"> |
105 | | - <Suspense |
106 | | - fallback={<SkeletonBox className="paginated-dependencies__skeleton" />} |
107 | | - > |
108 | | - <Await |
109 | | - resolve={versionAndDependencies} |
110 | | - errorElement={ |
111 | | - <div>Error occurred while loading required dependencies</div> |
112 | | - } |
113 | | - > |
114 | | - {(resolvedValue) => { |
115 | | - return ( |
116 | | - <> |
117 | | - <div className="paginated-dependencies__title"> |
118 | | - <Heading csLevel="3" csSize="3"> |
119 | | - Required mods ({resolvedValue[0].dependency_count}) |
120 | | - </Heading> |
121 | | - <span className="paginated-dependencies__description"> |
122 | | - This package requires the following packages to work. |
123 | | - </span> |
124 | | - </div> |
125 | | - <div className="paginated-dependencies__body"> |
126 | | - {resolvedValue[1].results.map((dep, key) => { |
127 | | - return <ListingDependency key={key} dependency={dep} />; |
128 | | - })} |
129 | | - </div> |
130 | | - <NewPagination |
131 | | - currentPage={currentPage} |
132 | | - pageSize={props.pageSize ?? 20} |
133 | | - totalCount={resolvedValue[0].dependency_count} |
134 | | - onPageChange={setParamsBlobValue( |
135 | | - setSearchParamsBlob, |
136 | | - searchParamsBlob, |
137 | | - "page" |
138 | | - )} |
139 | | - siblingCount={props.siblingCount ?? 4} |
140 | | - /> |
141 | | - </> |
142 | | - ); |
143 | | - }} |
144 | | - </Await> |
145 | | - </Suspense> |
| 30 | + <div className="paginated-dependencies__title"> |
| 31 | + <Heading csLevel="3" csSize="3"> |
| 32 | + Required mods ({version.dependency_count}) |
| 33 | + </Heading> |
| 34 | + <span className="paginated-dependencies__description"> |
| 35 | + This package requires the following packages to work. |
| 36 | + </span> |
| 37 | + </div> |
| 38 | + |
| 39 | + <div className="paginated-dependencies__body"> |
| 40 | + {dependencies.results.map((dep, idx) => ( |
| 41 | + <ListingDependency |
| 42 | + key={`${dep.name}-${dep.version_number}-${idx}`} |
| 43 | + dependency={dep} |
| 44 | + /> |
| 45 | + ))} |
| 46 | + </div> |
| 47 | + |
| 48 | + <NewPagination |
| 49 | + currentPage={page} |
| 50 | + pageSize={pageSize} |
| 51 | + totalCount={version.dependency_count} |
| 52 | + onPageChange={handlePageChange} |
| 53 | + siblingCount={siblingCount} |
| 54 | + /> |
146 | 55 | </div> |
147 | 56 | ); |
148 | | -}); |
| 57 | +} |
149 | 58 |
|
150 | 59 | PaginatedDependencies.displayName = "PaginatedDependencies"; |
151 | | - |
152 | | -export type SearchParamsType = { |
153 | | - page: number; |
154 | | -}; |
155 | | - |
156 | | -export const compareSearchParamBlobs = ( |
157 | | - b1: SearchParamsType, |
158 | | - b2: SearchParamsType |
159 | | -) => { |
160 | | - if (b1.page !== b2.page) return false; |
161 | | - return true; |
162 | | -}; |
163 | | - |
164 | | -export const searchParamsToBlob = (searchParams: URLSearchParams) => { |
165 | | - const initialPage = searchParams.get("page"); |
166 | | - |
167 | | - return { |
168 | | - page: |
169 | | - initialPage && |
170 | | - !Number.isNaN(Number.parseInt(initialPage)) && |
171 | | - Number.isSafeInteger(Number.parseInt(initialPage)) |
172 | | - ? Number.parseInt(initialPage) |
173 | | - : 1, |
174 | | - }; |
175 | | -}; |
0 commit comments