From 87b916412a419f4251ba5e932d938acf0946b9a1 Mon Sep 17 00:00:00 2001 From: Tolu Date: Mon, 6 Jan 2025 17:14:38 +0000 Subject: [PATCH 01/14] virtualized list with react window & throttled the request to prevent 429 errors --- package-lock.json | 61 ++++++++++++++++++- package.json | 6 +- src/api/lists.js | 6 +- src/common-components/account-short-entry.jsx | 2 +- src/detail-panels/lists/list-view.css | 20 ++++++ src/detail-panels/lists/list-view.jsx | 56 ++++++++++------- src/detail-panels/lists/lists.jsx | 39 +++++++----- 7 files changed, 148 insertions(+), 42 deletions(-) diff --git a/package-lock.json b/package-lock.json index 9d9dcb79..7be12216 100644 --- a/package-lock.json +++ b/package-lock.json @@ -16,16 +16,20 @@ "@mui/material": "^5.14.20", "@mui/styles": "^5.14.20", "@tanstack/react-query": "^5.61.4", + "@types/react-window": "^1.8.8", "@yornaath/batshit": "^0.10.1", "ag-grid-community": "^31.0.2", "ag-grid-react": "^31.0.3", "fuse.js": "^7.0.0", "iso-web": "^1.0.6", + "lodash.throttle": "^4.1.1", "react": "^18.2.0", "react-dom": "^18.2.0", - "react-router-dom": "^6.28.0" + "react-router-dom": "^6.28.0", + "react-window": "^1.8.11" }, "devDependencies": { + "@types/lodash.throttle": "^4.1.9", "@vitejs/plugin-react": "^4.3.4", "typescript": "^5", "vite": "^6.0.1" @@ -1671,6 +1675,23 @@ "dev": true, "license": "MIT" }, + "node_modules/@types/lodash": { + "version": "4.17.14", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.14.tgz", + "integrity": "sha512-jsxagdikDiDBeIRaPYtArcT8my4tN1og7MtMRquFT3XNA6axxyHDRUemqDz/taRDdOUn0GnGHRCuff4q48sW9A==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/lodash.throttle": { + "version": "4.1.9", + "resolved": "https://registry.npmjs.org/@types/lodash.throttle/-/lodash.throttle-4.1.9.tgz", + "integrity": "sha512-PCPVfpfueguWZQB7pJQK890F2scYKoDUL3iM522AptHWn7d5NQmeS/LTEHIcLr5PaTzl3dK2Z0xSUHHTHwaL5g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/lodash": "*" + } + }, "node_modules/@types/parse-json": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.2.tgz", @@ -1699,6 +1720,15 @@ "@types/react": "*" } }, + "node_modules/@types/react-window": { + "version": "1.8.8", + "resolved": "https://registry.npmjs.org/@types/react-window/-/react-window-1.8.8.tgz", + "integrity": "sha512-8Ls660bHR1AUA2kuRvVG9D/4XpRC6wjAaPT9dil7Ckc76eP9TKWZwwmgfq8Q1LANX3QNDnoU4Zp48A3w+zK69Q==", + "license": "MIT", + "dependencies": { + "@types/react": "*" + } + }, "node_modules/@types/retry": { "version": "0.12.2", "resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.2.tgz", @@ -2428,6 +2458,12 @@ "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==" }, + "node_modules/lodash.throttle": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.throttle/-/lodash.throttle-4.1.1.tgz", + "integrity": "sha512-wIkUCfVKpVsWo3JSZlc+8MB5it+2AN5W8J7YVMST30UrvcQNZ1Okbj+rbVniijTWE6FGYy4XJq/rHkas8qJMLQ==", + "license": "MIT" + }, "node_modules/loose-envify": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", @@ -2449,6 +2485,12 @@ "yallist": "^3.0.2" } }, + "node_modules/memoize-one": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-5.2.1.tgz", + "integrity": "sha512-zYiwtZUcYyXKo/np96AGZAckk+FWWsUdJ3cHGGmld7+AhvcWmQyGCYUh1hc4Q/pkOhb65dQR/pqCyK0cOaHz4Q==", + "license": "MIT" + }, "node_modules/mimic-fn": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz", @@ -2699,6 +2741,23 @@ "react-dom": ">=16.6.0" } }, + "node_modules/react-window": { + "version": "1.8.11", + "resolved": "https://registry.npmjs.org/react-window/-/react-window-1.8.11.tgz", + "integrity": "sha512-+SRbUVT2scadgFSWx+R1P754xHPEqvcfSfVX10QYg6POOz+WNgkN48pS+BtZNIMGiL1HYrSEiCkwsMS15QogEQ==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.0.0", + "memoize-one": ">=3.1.1 <6" + }, + "engines": { + "node": ">8.0.0" + }, + "peerDependencies": { + "react": "^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", + "react-dom": "^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, "node_modules/regenerator-runtime": { "version": "0.14.1", "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", diff --git a/package.json b/package.json index 29de7ec1..dfb42e1c 100644 --- a/package.json +++ b/package.json @@ -22,16 +22,20 @@ "@mui/material": "^5.14.20", "@mui/styles": "^5.14.20", "@tanstack/react-query": "^5.61.4", + "@types/react-window": "^1.8.8", "@yornaath/batshit": "^0.10.1", "ag-grid-community": "^31.0.2", "ag-grid-react": "^31.0.3", "fuse.js": "^7.0.0", "iso-web": "^1.0.6", + "lodash.throttle": "^4.1.1", "react": "^18.2.0", "react-dom": "^18.2.0", - "react-router-dom": "^6.28.0" + "react-router-dom": "^6.28.0", + "react-window": "^1.8.11" }, "devDependencies": { + "@types/lodash.throttle": "^4.1.9", "@vitejs/plugin-react": "^4.3.4", "typescript": "^5", "vite": "^6.0.1" diff --git a/src/api/lists.js b/src/api/lists.js index aaa4763c..a6b23fe0 100644 --- a/src/api/lists.js +++ b/src/api/lists.js @@ -4,6 +4,7 @@ import { unwrapShortHandle } from '.'; import { fetchClearskyApi, unwrapClearskyURL } from './core'; import { useResolveHandleOrDid } from './resolve-handle-or-did'; import { useInfiniteQuery, useQuery } from '@tanstack/react-query'; +import throttle from 'lodash.throttle' const PAGE_SIZE = 100; @@ -44,7 +45,7 @@ export function useListSize(listUrl) { return useQuery({ enabled: !!listUrl, queryKey: ['list-size', listUrl], - queryFn: () => getListSize(listUrl), + queryFn: () => throttledGetListSize(listUrl), }); } @@ -86,7 +87,6 @@ async function getList(shortHandle, currentPage = 1) { */ async function getListTotal(shortHandle) { const handleURL = 'get-list/total/' + unwrapShortHandle(shortHandle); - /** @type {{ data: { count: number; pages: number } }} */ const re = await fetchClearskyApi('v1', handleURL); return re.data; @@ -112,3 +112,5 @@ async function getListSize(listUrl) { } throw new Error('getListSize error: ' + resp.statusText); } + +const throttledGetListSize = throttle(getListSize,500) diff --git a/src/common-components/account-short-entry.jsx b/src/common-components/account-short-entry.jsx index 7b548452..748c82cf 100644 --- a/src/common-components/account-short-entry.jsx +++ b/src/common-components/account-short-entry.jsx @@ -140,7 +140,7 @@ function getAvatarDelay(account) { const rnd = Math.abs(hash) - Math.floor(Math.abs(hash)); delay = (rnd * 40).toFixed(3) + 's'; avatarDelays[avatarUrl] = delay; - console.log('Avatar delay', account.shortHandle, { delay, hash, rnd }); + //console.log('Avatar delay', account.shortHandle, { delay, hash, rnd }); return delay; } diff --git a/src/detail-panels/lists/list-view.css b/src/detail-panels/lists/list-view.css index 9c3ee525..c504bd17 100644 --- a/src/detail-panels/lists/list-view.css +++ b/src/detail-panels/lists/list-view.css @@ -50,4 +50,24 @@ overflow: hidden; text-overflow: ellipsis; padding-left: 0.5em; +} + +.lists-as-list-view .lists-entry .list-count { + grid-row: 1 / 2; + grid-column: 2 / 3; + opacity: 0.6; + overflow: hidden; + text-overflow: ellipsis; + padding-left: 0.5em; + color: darkred; +} + +.lists-as-list-view .lists-entry .list-count-no-desc { + grid-row: 1 / 3; + grid-column: 1/ 4; + opacity: 0.6; + overflow: hidden; + text-overflow: ellipsis; + padding-left: 0.5em; + color: rgb(2, 99, 2); } \ No newline at end of file diff --git a/src/detail-panels/lists/list-view.jsx b/src/detail-panels/lists/list-view.jsx index a3e60966..d65eb2f9 100644 --- a/src/detail-panels/lists/list-view.jsx +++ b/src/detail-panels/lists/list-view.jsx @@ -2,6 +2,7 @@ import { AccountShortEntry } from '../../common-components/account-short-entry'; import { FormatTimestamp } from '../../common-components/format-timestamp'; +import { useListSize } from '../../api/lists'; import './list-view.css'; @@ -11,46 +12,55 @@ import './list-view.css'; * list?: AccountListEntry[] * }} _ */ -export function ListView({ className, list }) { - return ( - - ); -} +// export function ListView({ className, list }) { +// return ( +// +// ); +// } /** * @param {{ * className?: string, - * entry: AccountListEntry + * entry: AccountListEntry, + * style:any + * listcount:number * }} _ */ -function ListViewEntry({ className, entry }) { +export function ListViewEntry({ className, entry, style, listcount }) { return ( -
  • -
    +
  • +
    + className="list-add-date" + />
    -
    - - {entry.name} - - +
    + {entry.description && ( + {listcount} + )} + {entry.name} + {entry.description && ' ' + entry.description} + {!entry.description && ( + {' ' + listcount} + )}
  • ); -} \ No newline at end of file +} diff --git a/src/detail-panels/lists/lists.jsx b/src/detail-panels/lists/lists.jsx index 39e52782..30225c13 100644 --- a/src/detail-panels/lists/lists.jsx +++ b/src/detail-panels/lists/lists.jsx @@ -6,8 +6,8 @@ import SearchIcon from '@mui/icons-material/Search'; import { Button, CircularProgress } from '@mui/material'; import { useSearchParams } from 'react-router-dom'; -import { useList, useListTotal } from '../../api/lists'; -import { ListView } from './list-view'; +import { useList, useListSize, useListTotal } from '../../api/lists'; +import { ListViewEntry } from './list-view'; import './lists.css'; import { SearchHeaderDebounced } from '../history/search-header'; @@ -15,6 +15,9 @@ import { localise, localiseNumberSuffix } from '../../localisation'; import { VisibleWithDelay } from '../../common-components/visible'; import { resolveHandleOrDID } from '../../api'; import { useAccountResolver } from '../account-resolver'; +import {FixedSizeList as List} from 'react-window' +import { useEffect } from 'react'; + export function Lists() { const accountQuery = useAccountResolver(); @@ -79,19 +82,27 @@ export function Lists() { } - - - {shouldShowLoadMore && ( - !isFetching && fetchNextPage()} +
      + -

      - Loading more... -

      - - )} + {({ index, data, style }) => { + const entry = data[index]; + const count = useListSize(entry.url) + return ( + + ); + }} +
      +
    ); } From 28edc6239bc67d9e551d6c959dad96127c95c925 Mon Sep 17 00:00:00 2001 From: Tolu Date: Mon, 6 Jan 2025 17:24:13 +0000 Subject: [PATCH 02/14] virtualized list with react window & throttled the request to prevent 429 errors --- src/detail-panels/lists/list-view.jsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/detail-panels/lists/list-view.jsx b/src/detail-panels/lists/list-view.jsx index d65eb2f9..2391aa28 100644 --- a/src/detail-panels/lists/list-view.jsx +++ b/src/detail-panels/lists/list-view.jsx @@ -51,14 +51,14 @@ export function ListViewEntry({ className, entry, style, listcount }) {
    {entry.description && ( - {listcount} + {listcount && listcount} )} {entry.name} {entry.description && ' ' + entry.description} {!entry.description && ( - {' ' + listcount} + {listcount && ' ' + listcount} )}
    From aeadb6f224d2a0f3993d3d2b7b35157150849c5b Mon Sep 17 00:00:00 2001 From: Tolu Date: Thu, 9 Jan 2025 11:55:38 +0000 Subject: [PATCH 03/14] fixed most issues,to address double windowing with react-window --- package-lock.json | 51 ++++++++- package.json | 6 +- src/detail-panels/lists/list-view.css | 13 ++- src/detail-panels/lists/list-view.jsx | 13 +-- src/detail-panels/lists/lists.jsx | 149 ++++++++++++++++++-------- 5 files changed, 174 insertions(+), 58 deletions(-) diff --git a/package-lock.json b/package-lock.json index 7be12216..0f33f329 100644 --- a/package-lock.json +++ b/package-lock.json @@ -26,10 +26,14 @@ "react": "^18.2.0", "react-dom": "^18.2.0", "react-router-dom": "^6.28.0", - "react-window": "^1.8.11" + "react-virtualized-auto-sizer": "^1.0.25", + "react-window": "^1.8.11", + "react-window-infinite-loader": "^1.0.9" }, "devDependencies": { "@types/lodash.throttle": "^4.1.9", + "@types/react-window-infinite-loader": "^1.0.9", + "@types/react-window-scroller": "^1.0.4", "@vitejs/plugin-react": "^4.3.4", "typescript": "^5", "vite": "^6.0.1" @@ -1729,6 +1733,28 @@ "@types/react": "*" } }, + "node_modules/@types/react-window-infinite-loader": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@types/react-window-infinite-loader/-/react-window-infinite-loader-1.0.9.tgz", + "integrity": "sha512-gEInTjQwURCnDOFyIEK2+fWB5gTjqwx30O62QfxA9stE5aiB6EWkGj4UMhc0axq7/FV++Gs/TGW8FtgEx0S6Tw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/react": "*", + "@types/react-window": "*" + } + }, + "node_modules/@types/react-window-scroller": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@types/react-window-scroller/-/react-window-scroller-1.0.4.tgz", + "integrity": "sha512-Y2KxgGC2/pCxAfMxgdO6XTdGLd1w5H7b29sJLzrBAjirEPXgTFho3tNAXiCOmO59k4XMwVzRr25CgSyxmjNhBg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/react": "*", + "@types/react-window": "*" + } + }, "node_modules/@types/retry": { "version": "0.12.2", "resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.2.tgz", @@ -2741,6 +2767,16 @@ "react-dom": ">=16.6.0" } }, + "node_modules/react-virtualized-auto-sizer": { + "version": "1.0.25", + "resolved": "https://registry.npmjs.org/react-virtualized-auto-sizer/-/react-virtualized-auto-sizer-1.0.25.tgz", + "integrity": "sha512-YHsksEGDfsHbHuaBVDYwJmcktblcHGafz4ZVuYPQYuSHMUGjpwmUCrAOcvMSGMwwk1eFWj1M/1GwYpNPuyhaBg==", + "license": "MIT", + "peerDependencies": { + "react": "^15.3.0 || ^16.0.0-alpha || ^17.0.0 || ^18.0.0 || ^19.0.0", + "react-dom": "^15.3.0 || ^16.0.0-alpha || ^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, "node_modules/react-window": { "version": "1.8.11", "resolved": "https://registry.npmjs.org/react-window/-/react-window-1.8.11.tgz", @@ -2758,6 +2794,19 @@ "react-dom": "^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, + "node_modules/react-window-infinite-loader": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/react-window-infinite-loader/-/react-window-infinite-loader-1.0.9.tgz", + "integrity": "sha512-5Hg89IdU4Vrp0RT8kZYKeTIxWZYhNkVXeI1HbKo01Vm/Z7qztDvXljwx16sMzsa9yapRJQW3ODZfMUw38SOWHw==", + "license": "MIT", + "engines": { + "node": ">8.0.0" + }, + "peerDependencies": { + "react": "^15.3.0 || ^16.0.0-alpha || ^17.0.0 || ^18.0.0", + "react-dom": "^15.3.0 || ^16.0.0-alpha || ^17.0.0 || ^18.0.0" + } + }, "node_modules/regenerator-runtime": { "version": "0.14.1", "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", diff --git a/package.json b/package.json index dfb42e1c..7cbf3812 100644 --- a/package.json +++ b/package.json @@ -32,10 +32,14 @@ "react": "^18.2.0", "react-dom": "^18.2.0", "react-router-dom": "^6.28.0", - "react-window": "^1.8.11" + "react-virtualized-auto-sizer": "^1.0.25", + "react-window": "^1.8.11", + "react-window-infinite-loader": "^1.0.9" }, "devDependencies": { "@types/lodash.throttle": "^4.1.9", + "@types/react-window-infinite-loader": "^1.0.9", + "@types/react-window-scroller": "^1.0.4", "@vitejs/plugin-react": "^4.3.4", "typescript": "^5", "vite": "^6.0.1" diff --git a/src/detail-panels/lists/list-view.css b/src/detail-panels/lists/list-view.css index c504bd17..0e06b669 100644 --- a/src/detail-panels/lists/list-view.css +++ b/src/detail-panels/lists/list-view.css @@ -19,6 +19,13 @@ white-space: nowrap; } +.lists-as-list-view .lists-entry .row-with-desc { + display: grid; + grid-template-columns: auto 1fr; + grid-template-rows: 1fr; + white-space: nowrap; +} + .lists-as-list-view .lists-entry .list-owner { grid-row: 1 / 2; grid-column: 1 / 2; @@ -39,7 +46,7 @@ .lists-as-list-view .lists-entry .list-name { grid-row: 1/ 2; grid-column: 1 / 2; - padding-left: 1.7em; + padding-left: 1.9em; font-weight: bold; } @@ -64,10 +71,8 @@ .lists-as-list-view .lists-entry .list-count-no-desc { grid-row: 1 / 3; - grid-column: 1/ 4; + grid-column: 1/ 3; opacity: 0.6; overflow: hidden; - text-overflow: ellipsis; - padding-left: 0.5em; color: rgb(2, 99, 2); } \ No newline at end of file diff --git a/src/detail-panels/lists/list-view.jsx b/src/detail-panels/lists/list-view.jsx index 2391aa28..be8dcb10 100644 --- a/src/detail-panels/lists/list-view.jsx +++ b/src/detail-panels/lists/list-view.jsx @@ -3,7 +3,6 @@ import { AccountShortEntry } from '../../common-components/account-short-entry'; import { FormatTimestamp } from '../../common-components/format-timestamp'; import { useListSize } from '../../api/lists'; - import './list-view.css'; /** @@ -41,7 +40,7 @@ export function ListViewEntry({ className, entry, style, listcount }) {
    - {entry.description && ( - {listcount && listcount} + {!!entry?.description && ( + {listcount} )} {entry.name} - {entry.description && ' ' + entry.description} + {!!entry?.description && ' ' + entry?.description} {!entry.description && ( - {listcount && ' ' + listcount} + {' ' + listcount} )}
    ); } + + diff --git a/src/detail-panels/lists/lists.jsx b/src/detail-panels/lists/lists.jsx index 30225c13..c9e5c9ae 100644 --- a/src/detail-panels/lists/lists.jsx +++ b/src/detail-panels/lists/lists.jsx @@ -7,7 +7,7 @@ import { Button, CircularProgress } from '@mui/material'; import { useSearchParams } from 'react-router-dom'; import { useList, useListSize, useListTotal } from '../../api/lists'; -import { ListViewEntry } from './list-view'; +import {ListViewEntry} from './list-view'; import './lists.css'; import { SearchHeaderDebounced } from '../history/search-header'; @@ -15,15 +15,17 @@ import { localise, localiseNumberSuffix } from '../../localisation'; import { VisibleWithDelay } from '../../common-components/visible'; import { resolveHandleOrDID } from '../../api'; import { useAccountResolver } from '../account-resolver'; -import {FixedSizeList as List} from 'react-window' -import { useEffect } from 'react'; - +import { FixedSizeList as List } from 'react-window'; +import Autosizer from 'react-virtualized-auto-sizer'; +import InfiniteLoader from 'react-window-infinite-loader'; export function Lists() { const accountQuery = useAccountResolver(); const shortHandle = accountQuery.data?.shortHandle; - const { data, fetchNextPage, hasNextPage, isLoading, isFetching } = useList(shortHandle); - const { data: totalData, isLoading: isLoadingTotal } = useListTotal(shortHandle); + const { data, fetchNextPage, hasNextPage, isLoading, isFetching } = + useList(shortHandle); + const { data: totalData, isLoading: isLoadingTotal } = + useListTotal(shortHandle); const [searchParams, setSearchParams] = useSearchParams(); const [tick, setTick] = useState(0); @@ -33,13 +35,15 @@ export function Lists() { const listsTotal = totalData?.count; const listPages = data?.pages || []; const allLists = listPages.flatMap((page) => page.lists); - const filteredLists = !search ? allLists : matchSearch(allLists, search, () => setTick(tick + 1)); + const filteredLists = !search + ? allLists + : matchSearch(allLists, search, () => setTick(tick + 1)); // Show loader for initial load if (isLoading) { return (
    - +
    {localise('Loading lists...', { uk: 'Завантаження списків...' })}
    @@ -47,7 +51,8 @@ export function Lists() { ); } - const shouldShowLoadMore = hasNextPage && (!search || filteredLists.length > 0); + const shouldShowLoadMore = + hasNextPage && (!search || filteredLists.length > 0); return ( <> @@ -55,54 +60,105 @@ export function Lists() {
    + setQ + />
    -

    - {isLoadingTotal && {localise("Counting lists...", {})}} - {listsTotal ? +

    + {isLoadingTotal && ( + + {localise('Counting lists...', {})} + + )} + {listsTotal ? ( <> {localise( - 'Member of ' + listsTotal.toLocaleString() + ' ' + localiseNumberSuffix('list', listsTotal) + ':', + 'Member of ' + + listsTotal.toLocaleString() + + ' ' + + localiseNumberSuffix('list', listsTotal) + + ':', { - uk: 'Входить до ' + listsTotal.toLocaleString() + ' ' + localiseNumberSuffix('списку', listsTotal) + ':' - })} - - {!showSearch && + uk: + 'Входить до ' + + listsTotal.toLocaleString() + + ' ' + + localiseNumberSuffix('списку', listsTotal) + + ':', + } + )} + + {!showSearch && ( - } + onClick={() => setShowSearch(true)} + > + + + )} - : - localise('Not a member of any lists', { uk: 'Не входить до жодного списку' }) - } + + ) : ( + localise('Not a member of any lists', { + uk: 'Не входить до жодного списку', + }) + )}

      - - {({ index, data, style }) => { - const entry = data[index]; - const count = useListSize(entry.url) - return ( - - ); +
      + > + + {({ height, width }) => ( + + {({ index, data, style }) => { + console.log("render", index) + const entry = data[index]; + + const count = useListSize(entry.url); + // const count = 999 + return ( + + ); + }} + + )} + +
    + + {shouldShowLoadMore && ( + !isFetching && fetchNextPage()} + > +

    + Loading more... +

    +
    + )} ); } @@ -114,13 +170,14 @@ export function Lists() { */ function matchSearch(blocklist, search, redraw) { const searchLowercase = search.toLowerCase(); - const filtered = blocklist.filter(entry => { + const filtered = blocklist.filter((entry) => { // if ((entry.handle || '').toLowerCase().includes(searchLowercase)) return true; if ((entry.name || '').toLowerCase().includes(searchLowercase)) return true; - if ((entry.description || '').toLowerCase().includes(searchLowercase)) return true; + if ((entry.description || '').toLowerCase().includes(searchLowercase)) + return true; resolveHandleOrDID(entry.did).then(redraw); return false; }); return filtered; -} \ No newline at end of file +} From 66df957e1746901b6288b182205c232410efd8e9 Mon Sep 17 00:00:00 2001 From: Tolu Date: Fri, 10 Jan 2025 13:38:41 +0000 Subject: [PATCH 04/14] outstanding issue, list items not rendering --- package-lock.json | 721 ++------------------------ package.json | 7 +- src/detail-panels/lists/list-view.css | 1 + src/detail-panels/lists/list-view.jsx | 12 +- src/detail-panels/lists/lists.jsx | 86 +-- vite.config.mjs | 7 + 6 files changed, 117 insertions(+), 717 deletions(-) diff --git a/package-lock.json b/package-lock.json index 0f33f329..4bbe5003 100644 --- a/package-lock.json +++ b/package-lock.json @@ -16,6 +16,7 @@ "@mui/material": "^5.14.20", "@mui/styles": "^5.14.20", "@tanstack/react-query": "^5.61.4", + "@tanstack/react-virtual": "^3.11.2", "@types/react-window": "^1.8.8", "@yornaath/batshit": "^0.10.1", "ag-grid-community": "^31.0.2", @@ -26,15 +27,15 @@ "react": "^18.2.0", "react-dom": "^18.2.0", "react-router-dom": "^6.28.0", - "react-virtualized-auto-sizer": "^1.0.25", - "react-window": "^1.8.11", - "react-window-infinite-loader": "^1.0.9" + "react-window": "^1.8.11" }, "devDependencies": { "@types/lodash.throttle": "^4.1.9", + "@types/react-virtualized": "^9.22.0", "@types/react-window-infinite-loader": "^1.0.9", "@types/react-window-scroller": "^1.0.4", "@vitejs/plugin-react": "^4.3.4", + "esbuild-plugin-react-virtualized": "^1.0.4", "typescript": "^5", "vite": "^6.0.1" } @@ -542,74 +543,6 @@ "resolved": "https://registry.npmjs.org/@emotion/weak-memoize/-/weak-memoize-0.3.1.tgz", "integrity": "sha512-EsBwpc7hBUJWAsNPBmJy4hxWx12v6bshQsldrVmjxJoc3isbxhOrF2IcCpaXxfvq03NwkI7sbsOLXbYuqF/8Ww==" }, - "node_modules/@esbuild/aix-ppc64": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.24.0.tgz", - "integrity": "sha512-WtKdFM7ls47zkKHFVzMz8opM7LkcsIp9amDUBIAWirg70RM71WRSjdILPsY5Uv1D42ZpUfaPILDlfactHgsRkw==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "aix" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/android-arm": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.24.0.tgz", - "integrity": "sha512-arAtTPo76fJ/ICkXWetLCc9EwEHKaeya4vMrReVlEIUCAUncH7M4bhMQ+M9Vf+FFOZJdTNMXNBrWwW+OXWpSew==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/android-arm64": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.24.0.tgz", - "integrity": "sha512-Vsm497xFM7tTIPYK9bNTYJyF/lsP590Qc1WxJdlB6ljCbdZKU9SY8i7+Iin4kyhV/KV5J2rOKsBQbB77Ab7L/w==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/android-x64": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.24.0.tgz", - "integrity": "sha512-t8GrvnFkiIY7pa7mMgJd7p8p8qqYIz1NYiAoKc75Zyv73L3DZW++oYMSHPRarcotTKuSs6m3hTOa5CKHaS02TQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, "node_modules/@esbuild/darwin-arm64": { "version": "0.24.0", "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.24.0.tgz", @@ -627,329 +560,6 @@ "node": ">=18" } }, - "node_modules/@esbuild/darwin-x64": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.24.0.tgz", - "integrity": "sha512-rgtz6flkVkh58od4PwTRqxbKH9cOjaXCMZgWD905JOzjFKW+7EiUObfd/Kav+A6Gyud6WZk9w+xu6QLytdi2OA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/freebsd-arm64": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.24.0.tgz", - "integrity": "sha512-6Mtdq5nHggwfDNLAHkPlyLBpE5L6hwsuXZX8XNmHno9JuL2+bg2BX5tRkwjyfn6sKbxZTq68suOjgWqCicvPXA==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/freebsd-x64": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.24.0.tgz", - "integrity": "sha512-D3H+xh3/zphoX8ck4S2RxKR6gHlHDXXzOf6f/9dbFt/NRBDIE33+cVa49Kil4WUjxMGW0ZIYBYtaGCa2+OsQwQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-arm": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.24.0.tgz", - "integrity": "sha512-gJKIi2IjRo5G6Glxb8d3DzYXlxdEj2NlkixPsqePSZMhLudqPhtZ4BUrpIuTjJYXxvF9njql+vRjB2oaC9XpBw==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-arm64": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.24.0.tgz", - "integrity": "sha512-TDijPXTOeE3eaMkRYpcy3LarIg13dS9wWHRdwYRnzlwlA370rNdZqbcp0WTyyV/k2zSxfko52+C7jU5F9Tfj1g==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-ia32": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.24.0.tgz", - "integrity": "sha512-K40ip1LAcA0byL05TbCQ4yJ4swvnbzHscRmUilrmP9Am7//0UjPreh4lpYzvThT2Quw66MhjG//20mrufm40mA==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-loong64": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.24.0.tgz", - "integrity": "sha512-0mswrYP/9ai+CU0BzBfPMZ8RVm3RGAN/lmOMgW4aFUSOQBjA31UP8Mr6DDhWSuMwj7jaWOT0p0WoZ6jeHhrD7g==", - "cpu": [ - "loong64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-mips64el": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.24.0.tgz", - "integrity": "sha512-hIKvXm0/3w/5+RDtCJeXqMZGkI2s4oMUGj3/jM0QzhgIASWrGO5/RlzAzm5nNh/awHE0A19h/CvHQe6FaBNrRA==", - "cpu": [ - "mips64el" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-ppc64": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.24.0.tgz", - "integrity": "sha512-HcZh5BNq0aC52UoocJxaKORfFODWXZxtBaaZNuN3PUX3MoDsChsZqopzi5UupRhPHSEHotoiptqikjN/B77mYQ==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-riscv64": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.24.0.tgz", - "integrity": "sha512-bEh7dMn/h3QxeR2KTy1DUszQjUrIHPZKyO6aN1X4BCnhfYhuQqedHaa5MxSQA/06j3GpiIlFGSsy1c7Gf9padw==", - "cpu": [ - "riscv64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-s390x": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.24.0.tgz", - "integrity": "sha512-ZcQ6+qRkw1UcZGPyrCiHHkmBaj9SiCD8Oqd556HldP+QlpUIe2Wgn3ehQGVoPOvZvtHm8HPx+bH20c9pvbkX3g==", - "cpu": [ - "s390x" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-x64": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.24.0.tgz", - "integrity": "sha512-vbutsFqQ+foy3wSSbmjBXXIJ6PL3scghJoM8zCL142cGaZKAdCZHyf+Bpu/MmX9zT9Q0zFBVKb36Ma5Fzfa8xA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/netbsd-x64": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.24.0.tgz", - "integrity": "sha512-hjQ0R/ulkO8fCYFsG0FZoH+pWgTTDreqpqY7UnQntnaKv95uP5iW3+dChxnx7C3trQQU40S+OgWhUVwCjVFLvg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/openbsd-arm64": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.24.0.tgz", - "integrity": "sha512-MD9uzzkPQbYehwcN583yx3Tu5M8EIoTD+tUgKF982WYL9Pf5rKy9ltgD0eUgs8pvKnmizxjXZyLt0z6DC3rRXg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/openbsd-x64": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.24.0.tgz", - "integrity": "sha512-4ir0aY1NGUhIC1hdoCzr1+5b43mw99uNwVzhIq1OY3QcEwPDO3B7WNXBzaKY5Nsf1+N11i1eOfFcq+D/gOS15Q==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/sunos-x64": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.24.0.tgz", - "integrity": "sha512-jVzdzsbM5xrotH+W5f1s+JtUy1UWgjU0Cf4wMvffTB8m6wP5/kx0KiaLHlbJO+dMgtxKV8RQ/JvtlFcdZ1zCPA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "sunos" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/win32-arm64": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.24.0.tgz", - "integrity": "sha512-iKc8GAslzRpBytO2/aN3d2yb2z8XTVfNV0PjGlCxKo5SgWmNXx82I/Q3aG1tFfS+A2igVCY97TJ8tnYwpUWLCA==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/win32-ia32": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.24.0.tgz", - "integrity": "sha512-vQW36KZolfIudCcTnaTpmLQ24Ha1RjygBo39/aLkM2kmjkWmZGEJ5Gn9l5/7tzXA42QGIoWbICfg6KLLkIw6yw==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/win32-x64": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.24.0.tgz", - "integrity": "sha512-7IAFPrjSQIJrGsK6flwg7NFmwBoSTyF3rl7If0hNUFQU4ilTsEPL6GuMuU9BfIWVVGuRnuIidkSMC+c0Otu8IA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, "node_modules/@floating-ui/core": { "version": "1.5.3", "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.5.3.tgz", @@ -1335,34 +945,6 @@ "node": ">=14.0.0" } }, - "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.28.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.28.1.tgz", - "integrity": "sha512-2aZp8AES04KI2dy3Ss6/MDjXbwBzj+i0GqKtWXgw2/Ma6E4jJvujryO6gJAghIRVz7Vwr9Gtl/8na3nDUKpraQ==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ] - }, - "node_modules/@rollup/rollup-android-arm64": { - "version": "4.28.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.28.1.tgz", - "integrity": "sha512-EbkK285O+1YMrg57xVA+Dp0tDBRB93/BZKph9XhMjezf6F4TpYjaUSuPt5J0fZXlSag0LmZAsTmdGGqPp4pQFA==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ] - }, "node_modules/@rollup/rollup-darwin-arm64": { "version": "4.28.1", "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.28.1.tgz", @@ -1377,230 +959,6 @@ "darwin" ] }, - "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.28.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.28.1.tgz", - "integrity": "sha512-WsvbOunsUk0wccO/TV4o7IKgloJ942hVFK1CLatwv6TJspcCZb9umQkPdvB7FihmdxgaKR5JyxDjWpCOp4uZlQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@rollup/rollup-freebsd-arm64": { - "version": "4.28.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.28.1.tgz", - "integrity": "sha512-HTDPdY1caUcU4qK23FeeGxCdJF64cKkqajU0iBnTVxS8F7H/7BewvYoG+va1KPSL63kQ1PGNyiwKOfReavzvNA==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ] - }, - "node_modules/@rollup/rollup-freebsd-x64": { - "version": "4.28.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.28.1.tgz", - "integrity": "sha512-m/uYasxkUevcFTeRSM9TeLyPe2QDuqtjkeoTpP9SW0XxUWfcYrGDMkO/m2tTw+4NMAF9P2fU3Mw4ahNvo7QmsQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ] - }, - "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.28.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.28.1.tgz", - "integrity": "sha512-QAg11ZIt6mcmzpNE6JZBpKfJaKkqTm1A9+y9O+frdZJEuhQxiugM05gnCWiANHj4RmbgeVJpTdmKRmH/a+0QbA==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.28.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.28.1.tgz", - "integrity": "sha512-dRP9PEBfolq1dmMcFqbEPSd9VlRuVWEGSmbxVEfiq2cs2jlZAl0YNxFzAQS2OrQmsLBLAATDMb3Z6MFv5vOcXg==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.28.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.28.1.tgz", - "integrity": "sha512-uGr8khxO+CKT4XU8ZUH1TTEUtlktK6Kgtv0+6bIFSeiSlnGJHG1tSFSjm41uQ9sAO/5ULx9mWOz70jYLyv1QkA==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.28.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.28.1.tgz", - "integrity": "sha512-QF54q8MYGAqMLrX2t7tNpi01nvq5RI59UBNx+3+37zoKX5KViPo/gk2QLhsuqok05sSCRluj0D00LzCwBikb0A==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-loongarch64-gnu": { - "version": "4.28.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.28.1.tgz", - "integrity": "sha512-vPul4uodvWvLhRco2w0GcyZcdyBfpfDRgNKU+p35AWEbJ/HPs1tOUrkSueVbBS0RQHAf/A+nNtDpvw95PeVKOA==", - "cpu": [ - "loong64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { - "version": "4.28.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.28.1.tgz", - "integrity": "sha512-pTnTdBuC2+pt1Rmm2SV7JWRqzhYpEILML4PKODqLz+C7Ou2apEV52h19CR7es+u04KlqplggmN9sqZlekg3R1A==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.28.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.28.1.tgz", - "integrity": "sha512-vWXy1Nfg7TPBSuAncfInmAI/WZDd5vOklyLJDdIRKABcZWojNDY0NJwruY2AcnCLnRJKSaBgf/GiJfauu8cQZA==", - "cpu": [ - "riscv64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.28.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.28.1.tgz", - "integrity": "sha512-/yqC2Y53oZjb0yz8PVuGOQQNOTwxcizudunl/tFs1aLvObTclTwZ0JhXF2XcPT/zuaymemCDSuuUPXJJyqeDOg==", - "cpu": [ - "s390x" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.28.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.28.1.tgz", - "integrity": "sha512-fzgeABz7rrAlKYB0y2kSEiURrI0691CSL0+KXwKwhxvj92VULEDQLpBYLHpF49MSiPG4sq5CK3qHMnb9tlCjBw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.28.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.28.1.tgz", - "integrity": "sha512-xQTDVzSGiMlSshpJCtudbWyRfLaNiVPXt1WgdWTwWz9n0U12cI2ZVtWe/Jgwyv/6wjL7b66uu61Vg0POWVfz4g==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.28.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.28.1.tgz", - "integrity": "sha512-wSXmDRVupJstFP7elGMgv+2HqXelQhuNf+IS4V+nUpNVi/GUiBgDmfwD0UGN3pcAnWsgKG3I52wMOBnk1VHr/A==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.28.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.28.1.tgz", - "integrity": "sha512-ZkyTJ/9vkgrE/Rk9vhMXhf8l9D+eAhbAVbsGsXKy2ohmJaWg0LPQLnIxRdRp/bKyr8tXuPlXhIoGlEB5XpJnGA==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.28.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.28.1.tgz", - "integrity": "sha512-ZvK2jBafvttJjoIdKm/Q/Bh7IJ1Ose9IBOwpOXcOvW3ikGTQGmKDgxTC6oCAzW6PynbkKP8+um1du81XJHZ0JA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, "node_modules/@tanstack/query-core": { "version": "5.61.4", "resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-5.61.4.tgz", @@ -1627,6 +985,33 @@ "react": "^18 || ^19" } }, + "node_modules/@tanstack/react-virtual": { + "version": "3.11.2", + "resolved": "https://registry.npmjs.org/@tanstack/react-virtual/-/react-virtual-3.11.2.tgz", + "integrity": "sha512-OuFzMXPF4+xZgx8UzJha0AieuMihhhaWG0tCqpp6tDzlFwOmNBPYMuLOtMJ1Tr4pXLHmgjcWhG6RlknY2oNTdQ==", + "license": "MIT", + "dependencies": { + "@tanstack/virtual-core": "3.11.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", + "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, + "node_modules/@tanstack/virtual-core": { + "version": "3.11.2", + "resolved": "https://registry.npmjs.org/@tanstack/virtual-core/-/virtual-core-3.11.2.tgz", + "integrity": "sha512-vTtpNt7mKCiZ1pwU9hfKPhpdVO2sVzFQsxoVBGtOSHxlrRRzYr8iQ2TlwbAcRYCcEiZ9ECAM8kBzH0v2+VzfKw==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + } + }, "node_modules/@types/babel__core": { "version": "7.20.5", "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", @@ -1724,6 +1109,17 @@ "@types/react": "*" } }, + "node_modules/@types/react-virtualized": { + "version": "9.22.0", + "resolved": "https://registry.npmjs.org/@types/react-virtualized/-/react-virtualized-9.22.0.tgz", + "integrity": "sha512-JL/YCCFZ123za//cj10Apk54F0UGFMrjOE0QHTuXt1KBMFrzLOGv9/x6Uc/pZ0Gaf4o6w61Fostvlw0DwuPXig==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/prop-types": "*", + "@types/react": "*" + } + }, "node_modules/@types/react-window": { "version": "1.8.8", "resolved": "https://registry.npmjs.org/@types/react-window/-/react-window-1.8.8.tgz", @@ -2137,6 +1533,16 @@ "@esbuild/win32-x64": "0.24.0" } }, + "node_modules/esbuild-plugin-react-virtualized": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/esbuild-plugin-react-virtualized/-/esbuild-plugin-react-virtualized-1.0.4.tgz", + "integrity": "sha512-/Y+82TBduHox0/uhJlTgUqi3ZWN+qZPF0xy9crkHQE2AOOdm76l6VY2F0Mdfvue9hqXz2FOlKHlHUVXNalHLzA==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "esbuild": "*" + } + }, "node_modules/escalade": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", @@ -2767,16 +2173,6 @@ "react-dom": ">=16.6.0" } }, - "node_modules/react-virtualized-auto-sizer": { - "version": "1.0.25", - "resolved": "https://registry.npmjs.org/react-virtualized-auto-sizer/-/react-virtualized-auto-sizer-1.0.25.tgz", - "integrity": "sha512-YHsksEGDfsHbHuaBVDYwJmcktblcHGafz4ZVuYPQYuSHMUGjpwmUCrAOcvMSGMwwk1eFWj1M/1GwYpNPuyhaBg==", - "license": "MIT", - "peerDependencies": { - "react": "^15.3.0 || ^16.0.0-alpha || ^17.0.0 || ^18.0.0 || ^19.0.0", - "react-dom": "^15.3.0 || ^16.0.0-alpha || ^17.0.0 || ^18.0.0 || ^19.0.0" - } - }, "node_modules/react-window": { "version": "1.8.11", "resolved": "https://registry.npmjs.org/react-window/-/react-window-1.8.11.tgz", @@ -2794,19 +2190,6 @@ "react-dom": "^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, - "node_modules/react-window-infinite-loader": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/react-window-infinite-loader/-/react-window-infinite-loader-1.0.9.tgz", - "integrity": "sha512-5Hg89IdU4Vrp0RT8kZYKeTIxWZYhNkVXeI1HbKo01Vm/Z7qztDvXljwx16sMzsa9yapRJQW3ODZfMUw38SOWHw==", - "license": "MIT", - "engines": { - "node": ">8.0.0" - }, - "peerDependencies": { - "react": "^15.3.0 || ^16.0.0-alpha || ^17.0.0 || ^18.0.0", - "react-dom": "^15.3.0 || ^16.0.0-alpha || ^17.0.0 || ^18.0.0" - } - }, "node_modules/regenerator-runtime": { "version": "0.14.1", "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", diff --git a/package.json b/package.json index 7cbf3812..e9b5f16f 100644 --- a/package.json +++ b/package.json @@ -22,6 +22,7 @@ "@mui/material": "^5.14.20", "@mui/styles": "^5.14.20", "@tanstack/react-query": "^5.61.4", + "@tanstack/react-virtual": "^3.11.2", "@types/react-window": "^1.8.8", "@yornaath/batshit": "^0.10.1", "ag-grid-community": "^31.0.2", @@ -32,15 +33,15 @@ "react": "^18.2.0", "react-dom": "^18.2.0", "react-router-dom": "^6.28.0", - "react-virtualized-auto-sizer": "^1.0.25", - "react-window": "^1.8.11", - "react-window-infinite-loader": "^1.0.9" + "react-window": "^1.8.11" }, "devDependencies": { "@types/lodash.throttle": "^4.1.9", + "@types/react-virtualized": "^9.22.0", "@types/react-window-infinite-loader": "^1.0.9", "@types/react-window-scroller": "^1.0.4", "@vitejs/plugin-react": "^4.3.4", + "esbuild-plugin-react-virtualized": "^1.0.4", "typescript": "^5", "vite": "^6.0.1" } diff --git a/src/detail-panels/lists/list-view.css b/src/detail-panels/lists/list-view.css index 0e06b669..78a1f65b 100644 --- a/src/detail-panels/lists/list-view.css +++ b/src/detail-panels/lists/list-view.css @@ -17,6 +17,7 @@ grid-template-columns: auto 1fr; grid-template-rows: 1fr; white-space: nowrap; + } .lists-as-list-view .lists-entry .row-with-desc { diff --git a/src/detail-panels/lists/list-view.jsx b/src/detail-panels/lists/list-view.jsx index be8dcb10..f7cde09e 100644 --- a/src/detail-panels/lists/list-view.jsx +++ b/src/detail-panels/lists/list-view.jsx @@ -30,10 +30,12 @@ import './list-view.css'; * className?: string, * entry: AccountListEntry, * style:any - * listcount:number * }} _ */ -export function ListViewEntry({ className, entry, style, listcount }) { +export function ListViewEntry({ className, entry, style }) { + const listcount = useListSize(entry?.url); + const count = listcount?.data?.count || '' + return (
  • @@ -50,18 +52,16 @@ export function ListViewEntry({ className, entry, style, listcount }) {
    {!!entry?.description && ( - {listcount} + {count} )} {entry.name} {!!entry?.description && ' ' + entry?.description} {!entry.description && ( - {' ' + listcount} + {' ' + count} )}
  • ); } - - diff --git a/src/detail-panels/lists/lists.jsx b/src/detail-panels/lists/lists.jsx index c9e5c9ae..15f919fa 100644 --- a/src/detail-panels/lists/lists.jsx +++ b/src/detail-panels/lists/lists.jsx @@ -1,13 +1,13 @@ // @ts-check -import { useState } from 'react'; +import { useState, useRef, useCallback } from 'react'; import SearchIcon from '@mui/icons-material/Search'; import { Button, CircularProgress } from '@mui/material'; import { useSearchParams } from 'react-router-dom'; -import { useList, useListSize, useListTotal } from '../../api/lists'; -import {ListViewEntry} from './list-view'; +import { useList, useListTotal } from '../../api/lists'; +import { ListViewEntry } from './list-view'; import './lists.css'; import { SearchHeaderDebounced } from '../history/search-header'; @@ -15,9 +15,7 @@ import { localise, localiseNumberSuffix } from '../../localisation'; import { VisibleWithDelay } from '../../common-components/visible'; import { resolveHandleOrDID } from '../../api'; import { useAccountResolver } from '../account-resolver'; -import { FixedSizeList as List } from 'react-window'; -import Autosizer from 'react-virtualized-auto-sizer'; -import InfiniteLoader from 'react-window-infinite-loader'; +import { useWindowVirtualizer } from '@tanstack/react-virtual'; export function Lists() { const accountQuery = useAccountResolver(); @@ -39,6 +37,17 @@ export function Lists() { ? allLists : matchSearch(allLists, search, () => setTick(tick + 1)); + const listRef = useRef(null); + + const rowVirtualizer = useWindowVirtualizer({ + count: filteredLists?.length, + estimateSize: () => 54, + overscan: 20, + gap: 50, + scrollMargin: listRef.current ? listRef.current.offsetTop : 0, + }); + + // Show loader for initial load if (isLoading) { return ( @@ -111,41 +120,40 @@ export function Lists() {
      - - {({ height, width }) => ( - - {({ index, data, style }) => { - console.log("render", index) - const entry = data[index]; - - const count = useListSize(entry.url); - // const count = 999 - return ( - - ); - }} - - )} - +
      +
      + {rowVirtualizer.getVirtualItems().map((virtualRow) => { + const entry = filteredLists[virtualRow.index]; + + return ( + + + ); + })} +
      +
    diff --git a/vite.config.mjs b/vite.config.mjs index 7f7bc353..e5880364 100644 --- a/vite.config.mjs +++ b/vite.config.mjs @@ -4,6 +4,8 @@ import { resolve, extname, join } from 'node:path'; import { readdirSync } from 'node:fs'; import { defineConfig } from 'vite'; import react from '@vitejs/plugin-react'; +import fixReactVirtualized from 'esbuild-plugin-react-virtualized' + function getInputHtmlFiles() { const srcDir = resolve(__dirname, 'src'); @@ -14,6 +16,11 @@ function getInputHtmlFiles() { export default defineConfig({ plugins: [react()], + optimizeDeps: { + esbuildOptions: { + plugins: [fixReactVirtualized], + }, + }, root: 'src', build: { outDir: resolve(__dirname, 'static'), From 9d3a6ae53c24b08b838f52f0a255849346a52966 Mon Sep 17 00:00:00 2001 From: Tolu Date: Fri, 10 Jan 2025 16:41:58 +0000 Subject: [PATCH 05/14] outstanding issue, list items not rendering --- src/detail-panels/lists/list-view.css | 17 ++++++++++++----- src/detail-panels/lists/list-view.jsx | 9 +++++---- 2 files changed, 17 insertions(+), 9 deletions(-) diff --git a/src/detail-panels/lists/list-view.css b/src/detail-panels/lists/list-view.css index 78a1f65b..dc262c80 100644 --- a/src/detail-panels/lists/list-view.css +++ b/src/detail-panels/lists/list-view.css @@ -1,6 +1,6 @@ .lists-as-list-view { margin: 0; - padding: 0 + padding: 0; } .lists-as-list-view .lists-entry { @@ -17,7 +17,14 @@ grid-template-columns: auto 1fr; grid-template-rows: 1fr; white-space: nowrap; - +} + +.lists-as-list-view .lists-entry .bottom-row { + display: flex; +} + +.lists-as-list-view .lists-entry .fixed-count-holder { + width: 40px; } .lists-as-list-view .lists-entry .row-with-desc { @@ -47,7 +54,7 @@ .lists-as-list-view .lists-entry .list-name { grid-row: 1/ 2; grid-column: 1 / 2; - padding-left: 1.9em; + padding-left: 0.5em; font-weight: bold; } @@ -72,8 +79,8 @@ .lists-as-list-view .lists-entry .list-count-no-desc { grid-row: 1 / 3; - grid-column: 1/ 3; + grid-column: 1/ 3; opacity: 0.6; overflow: hidden; color: rgb(2, 99, 2); -} \ No newline at end of file +} diff --git a/src/detail-panels/lists/list-view.jsx b/src/detail-panels/lists/list-view.jsx index f7cde09e..66ba54e2 100644 --- a/src/detail-panels/lists/list-view.jsx +++ b/src/detail-panels/lists/list-view.jsx @@ -50,10 +50,10 @@ export function ListViewEntry({ className, entry, style }) { className="list-add-date" /> -
    - {!!entry?.description && ( - {count} - )} +
    + {count}0 + +
    {entry.name} {!!entry?.description && ' ' + entry?.description} @@ -61,6 +61,7 @@ export function ListViewEntry({ className, entry, style }) { {!entry.description && ( {' ' + count} )} +
    ); From b0c953e02692f33d6c24653161ce0cf452d278d4 Mon Sep 17 00:00:00 2001 From: Tolu Date: Fri, 10 Jan 2025 17:35:29 +0000 Subject: [PATCH 06/14] outstanding issue, list items not fully rendering --- package-lock.json | 37 +-------------------------- package.json | 5 +--- src/detail-panels/lists/list-view.css | 3 ++- src/detail-panels/lists/list-view.jsx | 2 +- src/detail-panels/lists/lists.jsx | 27 +++++++++++-------- 5 files changed, 22 insertions(+), 52 deletions(-) diff --git a/package-lock.json b/package-lock.json index 4bbe5003..f793247c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -17,10 +17,10 @@ "@mui/styles": "^5.14.20", "@tanstack/react-query": "^5.61.4", "@tanstack/react-virtual": "^3.11.2", - "@types/react-window": "^1.8.8", "@yornaath/batshit": "^0.10.1", "ag-grid-community": "^31.0.2", "ag-grid-react": "^31.0.3", + "esbuild-plugin-react-virtualized": "^1.0.4", "fuse.js": "^7.0.0", "iso-web": "^1.0.6", "lodash.throttle": "^4.1.1", @@ -32,10 +32,7 @@ "devDependencies": { "@types/lodash.throttle": "^4.1.9", "@types/react-virtualized": "^9.22.0", - "@types/react-window-infinite-loader": "^1.0.9", - "@types/react-window-scroller": "^1.0.4", "@vitejs/plugin-react": "^4.3.4", - "esbuild-plugin-react-virtualized": "^1.0.4", "typescript": "^5", "vite": "^6.0.1" } @@ -1120,37 +1117,6 @@ "@types/react": "*" } }, - "node_modules/@types/react-window": { - "version": "1.8.8", - "resolved": "https://registry.npmjs.org/@types/react-window/-/react-window-1.8.8.tgz", - "integrity": "sha512-8Ls660bHR1AUA2kuRvVG9D/4XpRC6wjAaPT9dil7Ckc76eP9TKWZwwmgfq8Q1LANX3QNDnoU4Zp48A3w+zK69Q==", - "license": "MIT", - "dependencies": { - "@types/react": "*" - } - }, - "node_modules/@types/react-window-infinite-loader": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/@types/react-window-infinite-loader/-/react-window-infinite-loader-1.0.9.tgz", - "integrity": "sha512-gEInTjQwURCnDOFyIEK2+fWB5gTjqwx30O62QfxA9stE5aiB6EWkGj4UMhc0axq7/FV++Gs/TGW8FtgEx0S6Tw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/react": "*", - "@types/react-window": "*" - } - }, - "node_modules/@types/react-window-scroller": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@types/react-window-scroller/-/react-window-scroller-1.0.4.tgz", - "integrity": "sha512-Y2KxgGC2/pCxAfMxgdO6XTdGLd1w5H7b29sJLzrBAjirEPXgTFho3tNAXiCOmO59k4XMwVzRr25CgSyxmjNhBg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/react": "*", - "@types/react-window": "*" - } - }, "node_modules/@types/retry": { "version": "0.12.2", "resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.2.tgz", @@ -1537,7 +1503,6 @@ "version": "1.0.4", "resolved": "https://registry.npmjs.org/esbuild-plugin-react-virtualized/-/esbuild-plugin-react-virtualized-1.0.4.tgz", "integrity": "sha512-/Y+82TBduHox0/uhJlTgUqi3ZWN+qZPF0xy9crkHQE2AOOdm76l6VY2F0Mdfvue9hqXz2FOlKHlHUVXNalHLzA==", - "dev": true, "license": "MIT", "peerDependencies": { "esbuild": "*" diff --git a/package.json b/package.json index e9b5f16f..6df2d78b 100644 --- a/package.json +++ b/package.json @@ -23,10 +23,10 @@ "@mui/styles": "^5.14.20", "@tanstack/react-query": "^5.61.4", "@tanstack/react-virtual": "^3.11.2", - "@types/react-window": "^1.8.8", "@yornaath/batshit": "^0.10.1", "ag-grid-community": "^31.0.2", "ag-grid-react": "^31.0.3", + "esbuild-plugin-react-virtualized": "^1.0.4", "fuse.js": "^7.0.0", "iso-web": "^1.0.6", "lodash.throttle": "^4.1.1", @@ -38,10 +38,7 @@ "devDependencies": { "@types/lodash.throttle": "^4.1.9", "@types/react-virtualized": "^9.22.0", - "@types/react-window-infinite-loader": "^1.0.9", - "@types/react-window-scroller": "^1.0.4", "@vitejs/plugin-react": "^4.3.4", - "esbuild-plugin-react-virtualized": "^1.0.4", "typescript": "^5", "vite": "^6.0.1" } diff --git a/src/detail-panels/lists/list-view.css b/src/detail-panels/lists/list-view.css index dc262c80..d69568e6 100644 --- a/src/detail-panels/lists/list-view.css +++ b/src/detail-panels/lists/list-view.css @@ -24,7 +24,8 @@ } .lists-as-list-view .lists-entry .fixed-count-holder { - width: 40px; + max-width: 40px; + min-width: 20px; } .lists-as-list-view .lists-entry .row-with-desc { diff --git a/src/detail-panels/lists/list-view.jsx b/src/detail-panels/lists/list-view.jsx index 66ba54e2..32176f0f 100644 --- a/src/detail-panels/lists/list-view.jsx +++ b/src/detail-panels/lists/list-view.jsx @@ -51,7 +51,7 @@ export function ListViewEntry({ className, entry, style }) { />
    - {count}0 + {!!entry?.description && count}
    {entry.name} diff --git a/src/detail-panels/lists/lists.jsx b/src/detail-panels/lists/lists.jsx index 15f919fa..f34d1ca4 100644 --- a/src/detail-panels/lists/lists.jsx +++ b/src/detail-panels/lists/lists.jsx @@ -41,12 +41,13 @@ export function Lists() { const rowVirtualizer = useWindowVirtualizer({ count: filteredLists?.length, - estimateSize: () => 54, - overscan: 20, + estimateSize: () => 25, + overscan: 5, gap: 50, scrollMargin: listRef.current ? listRef.current.offsetTop : 0, }); + console.log(rowVirtualizer.getVirtualItems().length) // Show loader for initial load if (isLoading) { @@ -132,27 +133,33 @@ export function Lists() { height: `${rowVirtualizer.getTotalSize()}px`, }} > -
    { + const entry = filteredLists[virtualRow.index]; + + return ( +
    - {rowVirtualizer.getVirtualItems().map((virtualRow) => { - const entry = filteredLists[virtualRow.index]; - - return ( +
    ); })} -
    From f1291d7ee3e45e6440e7f2e96147a0393b9298cc Mon Sep 17 00:00:00 2001 From: Tolu Date: Tue, 14 Jan 2025 17:54:23 +0000 Subject: [PATCH 07/14] list count displayed, hook throttled to prevent server overload --- package-lock.json | 92 +++------------------------ package.json | 8 +-- src/detail-panels/lists/list-view.css | 17 ++--- src/detail-panels/lists/list-view.jsx | 50 +++++++-------- src/detail-panels/lists/lists.jsx | 63 +----------------- vite.config.mjs | 6 -- 6 files changed, 43 insertions(+), 193 deletions(-) diff --git a/package-lock.json b/package-lock.json index f793247c..8eb4e7e0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -15,23 +15,19 @@ "@mui/icons-material": "^5.14.16", "@mui/material": "^5.14.20", "@mui/styles": "^5.14.20", - "@tanstack/react-query": "^5.61.4", - "@tanstack/react-virtual": "^3.11.2", + "@tanstack/react-query": "^5.64.1", "@yornaath/batshit": "^0.10.1", "ag-grid-community": "^31.0.2", "ag-grid-react": "^31.0.3", - "esbuild-plugin-react-virtualized": "^1.0.4", "fuse.js": "^7.0.0", "iso-web": "^1.0.6", "lodash.throttle": "^4.1.1", "react": "^18.2.0", "react-dom": "^18.2.0", - "react-router-dom": "^6.28.0", - "react-window": "^1.8.11" + "react-router-dom": "^6.28.0" }, "devDependencies": { "@types/lodash.throttle": "^4.1.9", - "@types/react-virtualized": "^9.22.0", "@vitejs/plugin-react": "^4.3.4", "typescript": "^5", "vite": "^6.0.1" @@ -957,9 +953,9 @@ ] }, "node_modules/@tanstack/query-core": { - "version": "5.61.4", - "resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-5.61.4.tgz", - "integrity": "sha512-rsnemyhPvEG4ViZe0R2UQDM8NgQS/BNC5/Gf9RTs0TKN5thUhPUwnL2anWG4jxAGKFyDfvG7PXbx6MRq3hxi1w==", + "version": "5.64.1", + "resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-5.64.1.tgz", + "integrity": "sha512-978Wx4Wl4UJZbmvU/rkaM9cQtXXrbhK0lsz/UZhYIbyKYA8E4LdomTwyh2GHZ4oU0BKKoDH4YlKk2VscCUgNmg==", "license": "MIT", "funding": { "type": "github", @@ -967,12 +963,12 @@ } }, "node_modules/@tanstack/react-query": { - "version": "5.61.4", - "resolved": "https://registry.npmjs.org/@tanstack/react-query/-/react-query-5.61.4.tgz", - "integrity": "sha512-Nh5+0V4fRVShSeDHFTVvzJrvwTdafIvqxyZUrad71kJWL7J+J5Wrd/xcHTWfSL1mR/9eoufd2roXOpL3F16ECA==", + "version": "5.64.1", + "resolved": "https://registry.npmjs.org/@tanstack/react-query/-/react-query-5.64.1.tgz", + "integrity": "sha512-vW5ggHpIO2Yjj44b4sB+Fd3cdnlMJppXRBJkEHvld6FXh3j5dwWJoQo7mGtKI2RbSFyiyu/PhGAy0+Vv5ev9Eg==", "license": "MIT", "dependencies": { - "@tanstack/query-core": "5.61.4" + "@tanstack/query-core": "5.64.1" }, "funding": { "type": "github", @@ -982,33 +978,6 @@ "react": "^18 || ^19" } }, - "node_modules/@tanstack/react-virtual": { - "version": "3.11.2", - "resolved": "https://registry.npmjs.org/@tanstack/react-virtual/-/react-virtual-3.11.2.tgz", - "integrity": "sha512-OuFzMXPF4+xZgx8UzJha0AieuMihhhaWG0tCqpp6tDzlFwOmNBPYMuLOtMJ1Tr4pXLHmgjcWhG6RlknY2oNTdQ==", - "license": "MIT", - "dependencies": { - "@tanstack/virtual-core": "3.11.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/tannerlinsley" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", - "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" - } - }, - "node_modules/@tanstack/virtual-core": { - "version": "3.11.2", - "resolved": "https://registry.npmjs.org/@tanstack/virtual-core/-/virtual-core-3.11.2.tgz", - "integrity": "sha512-vTtpNt7mKCiZ1pwU9hfKPhpdVO2sVzFQsxoVBGtOSHxlrRRzYr8iQ2TlwbAcRYCcEiZ9ECAM8kBzH0v2+VzfKw==", - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/tannerlinsley" - } - }, "node_modules/@types/babel__core": { "version": "7.20.5", "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", @@ -1106,17 +1075,6 @@ "@types/react": "*" } }, - "node_modules/@types/react-virtualized": { - "version": "9.22.0", - "resolved": "https://registry.npmjs.org/@types/react-virtualized/-/react-virtualized-9.22.0.tgz", - "integrity": "sha512-JL/YCCFZ123za//cj10Apk54F0UGFMrjOE0QHTuXt1KBMFrzLOGv9/x6Uc/pZ0Gaf4o6w61Fostvlw0DwuPXig==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/prop-types": "*", - "@types/react": "*" - } - }, "node_modules/@types/retry": { "version": "0.12.2", "resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.2.tgz", @@ -1499,15 +1457,6 @@ "@esbuild/win32-x64": "0.24.0" } }, - "node_modules/esbuild-plugin-react-virtualized": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/esbuild-plugin-react-virtualized/-/esbuild-plugin-react-virtualized-1.0.4.tgz", - "integrity": "sha512-/Y+82TBduHox0/uhJlTgUqi3ZWN+qZPF0xy9crkHQE2AOOdm76l6VY2F0Mdfvue9hqXz2FOlKHlHUVXNalHLzA==", - "license": "MIT", - "peerDependencies": { - "esbuild": "*" - } - }, "node_modules/escalade": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", @@ -1882,12 +1831,6 @@ "yallist": "^3.0.2" } }, - "node_modules/memoize-one": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-5.2.1.tgz", - "integrity": "sha512-zYiwtZUcYyXKo/np96AGZAckk+FWWsUdJ3cHGGmld7+AhvcWmQyGCYUh1hc4Q/pkOhb65dQR/pqCyK0cOaHz4Q==", - "license": "MIT" - }, "node_modules/mimic-fn": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz", @@ -2138,23 +2081,6 @@ "react-dom": ">=16.6.0" } }, - "node_modules/react-window": { - "version": "1.8.11", - "resolved": "https://registry.npmjs.org/react-window/-/react-window-1.8.11.tgz", - "integrity": "sha512-+SRbUVT2scadgFSWx+R1P754xHPEqvcfSfVX10QYg6POOz+WNgkN48pS+BtZNIMGiL1HYrSEiCkwsMS15QogEQ==", - "license": "MIT", - "dependencies": { - "@babel/runtime": "^7.0.0", - "memoize-one": ">=3.1.1 <6" - }, - "engines": { - "node": ">8.0.0" - }, - "peerDependencies": { - "react": "^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", - "react-dom": "^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" - } - }, "node_modules/regenerator-runtime": { "version": "0.14.1", "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", diff --git a/package.json b/package.json index 6df2d78b..de3c6ef4 100644 --- a/package.json +++ b/package.json @@ -21,23 +21,19 @@ "@mui/icons-material": "^5.14.16", "@mui/material": "^5.14.20", "@mui/styles": "^5.14.20", - "@tanstack/react-query": "^5.61.4", - "@tanstack/react-virtual": "^3.11.2", + "@tanstack/react-query": "^5.64.1", "@yornaath/batshit": "^0.10.1", "ag-grid-community": "^31.0.2", "ag-grid-react": "^31.0.3", - "esbuild-plugin-react-virtualized": "^1.0.4", "fuse.js": "^7.0.0", "iso-web": "^1.0.6", "lodash.throttle": "^4.1.1", "react": "^18.2.0", "react-dom": "^18.2.0", - "react-router-dom": "^6.28.0", - "react-window": "^1.8.11" + "react-router-dom": "^6.28.0" }, "devDependencies": { "@types/lodash.throttle": "^4.1.9", - "@types/react-virtualized": "^9.22.0", "@vitejs/plugin-react": "^4.3.4", "typescript": "^5", "vite": "^6.0.1" diff --git a/src/detail-panels/lists/list-view.css b/src/detail-panels/lists/list-view.css index d69568e6..6c8dc267 100644 --- a/src/detail-panels/lists/list-view.css +++ b/src/detail-panels/lists/list-view.css @@ -5,7 +5,7 @@ .lists-as-list-view .lists-entry { list-style-type: none; - height: 3.5em; + height: auto; border-top: solid 1px #dbdbdb; padding-top: 0.4em; padding-left: 0.7em; @@ -63,19 +63,14 @@ grid-row: 1 / 2; grid-column: 2 / 3; opacity: 0.6; - overflow: hidden; - text-overflow: ellipsis; - padding-left: 0.5em; + padding-left: 1.7em; + white-space: normal; + word-wrap: break-word; } .lists-as-list-view .lists-entry .list-count { - grid-row: 1 / 2; - grid-column: 2 / 3; - opacity: 0.6; - overflow: hidden; - text-overflow: ellipsis; - padding-left: 0.5em; - color: darkred; + padding-left: 0.3em; + color: green; } .lists-as-list-view .lists-entry .list-count-no-desc { diff --git a/src/detail-panels/lists/list-view.jsx b/src/detail-panels/lists/list-view.jsx index 32176f0f..97bf4528 100644 --- a/src/detail-panels/lists/list-view.jsx +++ b/src/detail-panels/lists/list-view.jsx @@ -11,19 +11,15 @@ import './list-view.css'; * list?: AccountListEntry[] * }} _ */ -// export function ListView({ className, list }) { -// return ( -//
      -// {(list || []).map((entry, i) => ( -// -// ))} -//
    -// ); -// } +export function ListView({ className, list }) { + return ( +
      + {(list || []).map((entry, i) => ( + + ))} +
    + ); +} /** * @param {{ @@ -34,15 +30,15 @@ import './list-view.css'; */ export function ListViewEntry({ className, entry, style }) { const listcount = useListSize(entry?.url); - const count = listcount?.data?.count || '' + const count = listcount?.data?.count || ''; return ( -
  • +
  • -
    - {!!entry?.description && count} - -
    - {entry.name} - - {!!entry?.description && ' ' + entry?.description} +
    + + + {entry.name} + - {!entry.description && ( - {' ' + count} - )} -
    + {count}
    + {entry.description && ( +
    + {' ' + entry.description} +
    + )}
  • ); } diff --git a/src/detail-panels/lists/lists.jsx b/src/detail-panels/lists/lists.jsx index f34d1ca4..3cbd0245 100644 --- a/src/detail-panels/lists/lists.jsx +++ b/src/detail-panels/lists/lists.jsx @@ -1,13 +1,13 @@ // @ts-check -import { useState, useRef, useCallback } from 'react'; +import { useState} from 'react'; import SearchIcon from '@mui/icons-material/Search'; import { Button, CircularProgress } from '@mui/material'; import { useSearchParams } from 'react-router-dom'; import { useList, useListTotal } from '../../api/lists'; -import { ListViewEntry } from './list-view'; +import { ListView} from './list-view'; import './lists.css'; import { SearchHeaderDebounced } from '../history/search-header'; @@ -15,7 +15,6 @@ import { localise, localiseNumberSuffix } from '../../localisation'; import { VisibleWithDelay } from '../../common-components/visible'; import { resolveHandleOrDID } from '../../api'; import { useAccountResolver } from '../account-resolver'; -import { useWindowVirtualizer } from '@tanstack/react-virtual'; export function Lists() { const accountQuery = useAccountResolver(); @@ -37,18 +36,6 @@ export function Lists() { ? allLists : matchSearch(allLists, search, () => setTick(tick + 1)); - const listRef = useRef(null); - - const rowVirtualizer = useWindowVirtualizer({ - count: filteredLists?.length, - estimateSize: () => 25, - overscan: 5, - gap: 50, - scrollMargin: listRef.current ? listRef.current.offsetTop : 0, - }); - - console.log(rowVirtualizer.getVirtualItems().length) - // Show loader for initial load if (isLoading) { return ( @@ -118,51 +105,7 @@ export function Lists() { )} -
      -
      -
      - - {rowVirtualizer.getVirtualItems().map((virtualRow) => { - const entry = filteredLists[virtualRow.index]; - - return ( -
      - - -
      - ); - })} -
      -
      -
    + {shouldShowLoadMore && ( Date: Tue, 14 Jan 2025 18:03:32 +0000 Subject: [PATCH 08/14] list count displayed, hook throttled to prevent server overload --- package-lock.json | 643 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 643 insertions(+) diff --git a/package-lock.json b/package-lock.json index 8eb4e7e0..412d8f25 100644 --- a/package-lock.json +++ b/package-lock.json @@ -536,6 +536,74 @@ "resolved": "https://registry.npmjs.org/@emotion/weak-memoize/-/weak-memoize-0.3.1.tgz", "integrity": "sha512-EsBwpc7hBUJWAsNPBmJy4hxWx12v6bshQsldrVmjxJoc3isbxhOrF2IcCpaXxfvq03NwkI7sbsOLXbYuqF/8Ww==" }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.24.0.tgz", + "integrity": "sha512-WtKdFM7ls47zkKHFVzMz8opM7LkcsIp9amDUBIAWirg70RM71WRSjdILPsY5Uv1D42ZpUfaPILDlfactHgsRkw==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.24.0.tgz", + "integrity": "sha512-arAtTPo76fJ/ICkXWetLCc9EwEHKaeya4vMrReVlEIUCAUncH7M4bhMQ+M9Vf+FFOZJdTNMXNBrWwW+OXWpSew==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.24.0.tgz", + "integrity": "sha512-Vsm497xFM7tTIPYK9bNTYJyF/lsP590Qc1WxJdlB6ljCbdZKU9SY8i7+Iin4kyhV/KV5J2rOKsBQbB77Ab7L/w==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.24.0.tgz", + "integrity": "sha512-t8GrvnFkiIY7pa7mMgJd7p8p8qqYIz1NYiAoKc75Zyv73L3DZW++oYMSHPRarcotTKuSs6m3hTOa5CKHaS02TQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, "node_modules/@esbuild/darwin-arm64": { "version": "0.24.0", "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.24.0.tgz", @@ -553,6 +621,329 @@ "node": ">=18" } }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.24.0.tgz", + "integrity": "sha512-rgtz6flkVkh58od4PwTRqxbKH9cOjaXCMZgWD905JOzjFKW+7EiUObfd/Kav+A6Gyud6WZk9w+xu6QLytdi2OA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.24.0.tgz", + "integrity": "sha512-6Mtdq5nHggwfDNLAHkPlyLBpE5L6hwsuXZX8XNmHno9JuL2+bg2BX5tRkwjyfn6sKbxZTq68suOjgWqCicvPXA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.24.0.tgz", + "integrity": "sha512-D3H+xh3/zphoX8ck4S2RxKR6gHlHDXXzOf6f/9dbFt/NRBDIE33+cVa49Kil4WUjxMGW0ZIYBYtaGCa2+OsQwQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.24.0.tgz", + "integrity": "sha512-gJKIi2IjRo5G6Glxb8d3DzYXlxdEj2NlkixPsqePSZMhLudqPhtZ4BUrpIuTjJYXxvF9njql+vRjB2oaC9XpBw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.24.0.tgz", + "integrity": "sha512-TDijPXTOeE3eaMkRYpcy3LarIg13dS9wWHRdwYRnzlwlA370rNdZqbcp0WTyyV/k2zSxfko52+C7jU5F9Tfj1g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.24.0.tgz", + "integrity": "sha512-K40ip1LAcA0byL05TbCQ4yJ4swvnbzHscRmUilrmP9Am7//0UjPreh4lpYzvThT2Quw66MhjG//20mrufm40mA==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.24.0.tgz", + "integrity": "sha512-0mswrYP/9ai+CU0BzBfPMZ8RVm3RGAN/lmOMgW4aFUSOQBjA31UP8Mr6DDhWSuMwj7jaWOT0p0WoZ6jeHhrD7g==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.24.0.tgz", + "integrity": "sha512-hIKvXm0/3w/5+RDtCJeXqMZGkI2s4oMUGj3/jM0QzhgIASWrGO5/RlzAzm5nNh/awHE0A19h/CvHQe6FaBNrRA==", + "cpu": [ + "mips64el" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.24.0.tgz", + "integrity": "sha512-HcZh5BNq0aC52UoocJxaKORfFODWXZxtBaaZNuN3PUX3MoDsChsZqopzi5UupRhPHSEHotoiptqikjN/B77mYQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.24.0.tgz", + "integrity": "sha512-bEh7dMn/h3QxeR2KTy1DUszQjUrIHPZKyO6aN1X4BCnhfYhuQqedHaa5MxSQA/06j3GpiIlFGSsy1c7Gf9padw==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.24.0.tgz", + "integrity": "sha512-ZcQ6+qRkw1UcZGPyrCiHHkmBaj9SiCD8Oqd556HldP+QlpUIe2Wgn3ehQGVoPOvZvtHm8HPx+bH20c9pvbkX3g==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.24.0.tgz", + "integrity": "sha512-vbutsFqQ+foy3wSSbmjBXXIJ6PL3scghJoM8zCL142cGaZKAdCZHyf+Bpu/MmX9zT9Q0zFBVKb36Ma5Fzfa8xA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.24.0.tgz", + "integrity": "sha512-hjQ0R/ulkO8fCYFsG0FZoH+pWgTTDreqpqY7UnQntnaKv95uP5iW3+dChxnx7C3trQQU40S+OgWhUVwCjVFLvg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-arm64": { + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.24.0.tgz", + "integrity": "sha512-MD9uzzkPQbYehwcN583yx3Tu5M8EIoTD+tUgKF982WYL9Pf5rKy9ltgD0eUgs8pvKnmizxjXZyLt0z6DC3rRXg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.24.0.tgz", + "integrity": "sha512-4ir0aY1NGUhIC1hdoCzr1+5b43mw99uNwVzhIq1OY3QcEwPDO3B7WNXBzaKY5Nsf1+N11i1eOfFcq+D/gOS15Q==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.24.0.tgz", + "integrity": "sha512-jVzdzsbM5xrotH+W5f1s+JtUy1UWgjU0Cf4wMvffTB8m6wP5/kx0KiaLHlbJO+dMgtxKV8RQ/JvtlFcdZ1zCPA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.24.0.tgz", + "integrity": "sha512-iKc8GAslzRpBytO2/aN3d2yb2z8XTVfNV0PjGlCxKo5SgWmNXx82I/Q3aG1tFfS+A2igVCY97TJ8tnYwpUWLCA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.24.0.tgz", + "integrity": "sha512-vQW36KZolfIudCcTnaTpmLQ24Ha1RjygBo39/aLkM2kmjkWmZGEJ5Gn9l5/7tzXA42QGIoWbICfg6KLLkIw6yw==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.24.0.tgz", + "integrity": "sha512-7IAFPrjSQIJrGsK6flwg7NFmwBoSTyF3rl7If0hNUFQU4ilTsEPL6GuMuU9BfIWVVGuRnuIidkSMC+c0Otu8IA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, "node_modules/@floating-ui/core": { "version": "1.5.3", "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.5.3.tgz", @@ -938,6 +1329,34 @@ "node": ">=14.0.0" } }, + "node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.28.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.28.1.tgz", + "integrity": "sha512-2aZp8AES04KI2dy3Ss6/MDjXbwBzj+i0GqKtWXgw2/Ma6E4jJvujryO6gJAghIRVz7Vwr9Gtl/8na3nDUKpraQ==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-android-arm64": { + "version": "4.28.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.28.1.tgz", + "integrity": "sha512-EbkK285O+1YMrg57xVA+Dp0tDBRB93/BZKph9XhMjezf6F4TpYjaUSuPt5J0fZXlSag0LmZAsTmdGGqPp4pQFA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, "node_modules/@rollup/rollup-darwin-arm64": { "version": "4.28.1", "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.28.1.tgz", @@ -952,6 +1371,230 @@ "darwin" ] }, + "node_modules/@rollup/rollup-darwin-x64": { + "version": "4.28.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.28.1.tgz", + "integrity": "sha512-WsvbOunsUk0wccO/TV4o7IKgloJ942hVFK1CLatwv6TJspcCZb9umQkPdvB7FihmdxgaKR5JyxDjWpCOp4uZlQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-freebsd-arm64": { + "version": "4.28.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.28.1.tgz", + "integrity": "sha512-HTDPdY1caUcU4qK23FeeGxCdJF64cKkqajU0iBnTVxS8F7H/7BewvYoG+va1KPSL63kQ1PGNyiwKOfReavzvNA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-freebsd-x64": { + "version": "4.28.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.28.1.tgz", + "integrity": "sha512-m/uYasxkUevcFTeRSM9TeLyPe2QDuqtjkeoTpP9SW0XxUWfcYrGDMkO/m2tTw+4NMAF9P2fU3Mw4ahNvo7QmsQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.28.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.28.1.tgz", + "integrity": "sha512-QAg11ZIt6mcmzpNE6JZBpKfJaKkqTm1A9+y9O+frdZJEuhQxiugM05gnCWiANHj4RmbgeVJpTdmKRmH/a+0QbA==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm-musleabihf": { + "version": "4.28.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.28.1.tgz", + "integrity": "sha512-dRP9PEBfolq1dmMcFqbEPSd9VlRuVWEGSmbxVEfiq2cs2jlZAl0YNxFzAQS2OrQmsLBLAATDMb3Z6MFv5vOcXg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.28.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.28.1.tgz", + "integrity": "sha512-uGr8khxO+CKT4XU8ZUH1TTEUtlktK6Kgtv0+6bIFSeiSlnGJHG1tSFSjm41uQ9sAO/5ULx9mWOz70jYLyv1QkA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.28.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.28.1.tgz", + "integrity": "sha512-QF54q8MYGAqMLrX2t7tNpi01nvq5RI59UBNx+3+37zoKX5KViPo/gk2QLhsuqok05sSCRluj0D00LzCwBikb0A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loongarch64-gnu": { + "version": "4.28.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.28.1.tgz", + "integrity": "sha512-vPul4uodvWvLhRco2w0GcyZcdyBfpfDRgNKU+p35AWEbJ/HPs1tOUrkSueVbBS0RQHAf/A+nNtDpvw95PeVKOA==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { + "version": "4.28.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.28.1.tgz", + "integrity": "sha512-pTnTdBuC2+pt1Rmm2SV7JWRqzhYpEILML4PKODqLz+C7Ou2apEV52h19CR7es+u04KlqplggmN9sqZlekg3R1A==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.28.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.28.1.tgz", + "integrity": "sha512-vWXy1Nfg7TPBSuAncfInmAI/WZDd5vOklyLJDdIRKABcZWojNDY0NJwruY2AcnCLnRJKSaBgf/GiJfauu8cQZA==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-s390x-gnu": { + "version": "4.28.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.28.1.tgz", + "integrity": "sha512-/yqC2Y53oZjb0yz8PVuGOQQNOTwxcizudunl/tFs1aLvObTclTwZ0JhXF2XcPT/zuaymemCDSuuUPXJJyqeDOg==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.28.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.28.1.tgz", + "integrity": "sha512-fzgeABz7rrAlKYB0y2kSEiURrI0691CSL0+KXwKwhxvj92VULEDQLpBYLHpF49MSiPG4sq5CK3qHMnb9tlCjBw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.28.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.28.1.tgz", + "integrity": "sha512-xQTDVzSGiMlSshpJCtudbWyRfLaNiVPXt1WgdWTwWz9n0U12cI2ZVtWe/Jgwyv/6wjL7b66uu61Vg0POWVfz4g==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.28.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.28.1.tgz", + "integrity": "sha512-wSXmDRVupJstFP7elGMgv+2HqXelQhuNf+IS4V+nUpNVi/GUiBgDmfwD0UGN3pcAnWsgKG3I52wMOBnk1VHr/A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.28.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.28.1.tgz", + "integrity": "sha512-ZkyTJ/9vkgrE/Rk9vhMXhf8l9D+eAhbAVbsGsXKy2ohmJaWg0LPQLnIxRdRp/bKyr8tXuPlXhIoGlEB5XpJnGA==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.28.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.28.1.tgz", + "integrity": "sha512-ZvK2jBafvttJjoIdKm/Q/Bh7IJ1Ose9IBOwpOXcOvW3ikGTQGmKDgxTC6oCAzW6PynbkKP8+um1du81XJHZ0JA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, "node_modules/@tanstack/query-core": { "version": "5.64.1", "resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-5.64.1.tgz", From bca248f0746dff2bbb9198fb43df971b3a6c8952 Mon Sep 17 00:00:00 2001 From: Tolu Date: Tue, 14 Jan 2025 18:10:31 +0000 Subject: [PATCH 09/14] list count displayed, hook throttled to prevent server overload --- src/detail-panels/lists/list-view.css | 23 ----------------------- 1 file changed, 23 deletions(-) diff --git a/src/detail-panels/lists/list-view.css b/src/detail-panels/lists/list-view.css index 6c8dc267..ad5a0e02 100644 --- a/src/detail-panels/lists/list-view.css +++ b/src/detail-panels/lists/list-view.css @@ -19,22 +19,6 @@ white-space: nowrap; } -.lists-as-list-view .lists-entry .bottom-row { - display: flex; -} - -.lists-as-list-view .lists-entry .fixed-count-holder { - max-width: 40px; - min-width: 20px; -} - -.lists-as-list-view .lists-entry .row-with-desc { - display: grid; - grid-template-columns: auto 1fr; - grid-template-rows: 1fr; - white-space: nowrap; -} - .lists-as-list-view .lists-entry .list-owner { grid-row: 1 / 2; grid-column: 1 / 2; @@ -73,10 +57,3 @@ color: green; } -.lists-as-list-view .lists-entry .list-count-no-desc { - grid-row: 1 / 3; - grid-column: 1/ 3; - opacity: 0.6; - overflow: hidden; - color: rgb(2, 99, 2); -} From a31c65b71f4d520b7de47e93ca6267c9722f52c1 Mon Sep 17 00:00:00 2001 From: Noah Manneschmidt Date: Fri, 24 Jan 2025 19:29:19 -0800 Subject: [PATCH 10/14] swap lodash.throttle for p-queue --- package-lock.json | 60 +++++++++++++++++++++++++++-------------------- package.json | 3 +-- src/api/lists.js | 19 +++++++++++---- 3 files changed, 51 insertions(+), 31 deletions(-) diff --git a/package-lock.json b/package-lock.json index 412d8f25..f59069b6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -21,13 +21,12 @@ "ag-grid-react": "^31.0.3", "fuse.js": "^7.0.0", "iso-web": "^1.0.6", - "lodash.throttle": "^4.1.1", + "p-queue": "8.1.0", "react": "^18.2.0", "react-dom": "^18.2.0", "react-router-dom": "^6.28.0" }, "devDependencies": { - "@types/lodash.throttle": "^4.1.9", "@vitejs/plugin-react": "^4.3.4", "typescript": "^5", "vite": "^6.0.1" @@ -1673,23 +1672,6 @@ "dev": true, "license": "MIT" }, - "node_modules/@types/lodash": { - "version": "4.17.14", - "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.14.tgz", - "integrity": "sha512-jsxagdikDiDBeIRaPYtArcT8my4tN1og7MtMRquFT3XNA6axxyHDRUemqDz/taRDdOUn0GnGHRCuff4q48sW9A==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/lodash.throttle": { - "version": "4.1.9", - "resolved": "https://registry.npmjs.org/@types/lodash.throttle/-/lodash.throttle-4.1.9.tgz", - "integrity": "sha512-PCPVfpfueguWZQB7pJQK890F2scYKoDUL3iM522AptHWn7d5NQmeS/LTEHIcLr5PaTzl3dK2Z0xSUHHTHwaL5g==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/lodash": "*" - } - }, "node_modules/@types/parse-json": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.2.tgz", @@ -2121,6 +2103,12 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/eventemitter3": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz", + "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==", + "license": "MIT" + }, "node_modules/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", @@ -2447,12 +2435,6 @@ "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==" }, - "node_modules/lodash.throttle": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/lodash.throttle/-/lodash.throttle-4.1.1.tgz", - "integrity": "sha512-wIkUCfVKpVsWo3JSZlc+8MB5it+2AN5W8J7YVMST30UrvcQNZ1Okbj+rbVniijTWE6FGYy4XJq/rHkas8qJMLQ==", - "license": "MIT" - }, "node_modules/loose-envify": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", @@ -2531,6 +2513,22 @@ "node": ">=0.10.0" } }, + "node_modules/p-queue": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/p-queue/-/p-queue-8.1.0.tgz", + "integrity": "sha512-mxLDbbGIBEXTJL0zEx8JIylaj3xQ7Z/7eEVjcF9fJX4DBiH9oqe+oahYnlKKxm0Ci9TlWTyhSHgygxMxjIB2jw==", + "license": "MIT", + "dependencies": { + "eventemitter3": "^5.0.1", + "p-timeout": "^6.1.2" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/p-retry": { "version": "6.2.1", "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-6.2.1.tgz", @@ -2548,6 +2546,18 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/p-timeout": { + "version": "6.1.4", + "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-6.1.4.tgz", + "integrity": "sha512-MyIV3ZA/PmyBN/ud8vV9XzwTrNtR4jFrObymZYnZqMmW0zA8Z17vnT0rBgFE/TlohB+YCHqXMgZzb3Csp49vqg==", + "license": "MIT", + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/parent-module": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", diff --git a/package.json b/package.json index de3c6ef4..d141910e 100644 --- a/package.json +++ b/package.json @@ -27,13 +27,12 @@ "ag-grid-react": "^31.0.3", "fuse.js": "^7.0.0", "iso-web": "^1.0.6", - "lodash.throttle": "^4.1.1", + "p-queue": "8.1.0", "react": "^18.2.0", "react-dom": "^18.2.0", "react-router-dom": "^6.28.0" }, "devDependencies": { - "@types/lodash.throttle": "^4.1.9", "@vitejs/plugin-react": "^4.3.4", "typescript": "^5", "vite": "^6.0.1" diff --git a/src/api/lists.js b/src/api/lists.js index a6b23fe0..a860b62b 100644 --- a/src/api/lists.js +++ b/src/api/lists.js @@ -4,7 +4,7 @@ import { unwrapShortHandle } from '.'; import { fetchClearskyApi, unwrapClearskyURL } from './core'; import { useResolveHandleOrDid } from './resolve-handle-or-did'; import { useInfiniteQuery, useQuery } from '@tanstack/react-query'; -import throttle from 'lodash.throttle' +import PQueue from 'p-queue'; const PAGE_SIZE = 100; @@ -45,7 +45,7 @@ export function useListSize(listUrl) { return useQuery({ enabled: !!listUrl, queryKey: ['list-size', listUrl], - queryFn: () => throttledGetListSize(listUrl), + queryFn: () => getListSize(listUrl), }); } @@ -101,7 +101,9 @@ async function getListSize(listUrl) { const apiUrl = unwrapClearskyURL( `/api/v1/anon/get-list/specific/total/${encodeURIComponent(listUrl)}` ); - const resp = await fetch(apiUrl); + const resp = await listSizeQueue.add(() => fetch(apiUrl), { + throwOnTimeout: true, + }); if (resp.ok) { /** @type {{ data: { count: number }, list_uri: string }} */ const respData = await resp.json(); @@ -113,4 +115,13 @@ async function getListSize(listUrl) { throw new Error('getListSize error: ' + resp.statusText); } -const throttledGetListSize = throttle(getListSize,500) +/** + * create a queue where only one request can be in flight at a time, + * and at most 1 may be sent in any 500 millisecond interval + */ +const listSizeQueue = new PQueue({ + concurrency: 1, + intervalCap: 1, + interval: 500, + timeout: 500, +}); From b6d0b3032f279b501292ef4fe193e26a228af1d1 Mon Sep 17 00:00:00 2001 From: Noah Manneschmidt Date: Fri, 24 Jan 2025 19:37:01 -0800 Subject: [PATCH 11/14] add a small loading indicator for list entry size --- src/detail-panels/lists/list-view.jsx | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/detail-panels/lists/list-view.jsx b/src/detail-panels/lists/list-view.jsx index 97bf4528..d00cf8b3 100644 --- a/src/detail-panels/lists/list-view.jsx +++ b/src/detail-panels/lists/list-view.jsx @@ -1,5 +1,6 @@ // @ts-check +import { CircularProgress } from '@mui/material'; import { AccountShortEntry } from '../../common-components/account-short-entry'; import { FormatTimestamp } from '../../common-components/format-timestamp'; import { useListSize } from '../../api/lists'; @@ -29,8 +30,8 @@ export function ListView({ className, list }) { * }} _ */ export function ListViewEntry({ className, entry, style }) { - const listcount = useListSize(entry?.url); - const count = listcount?.data?.count || ''; + const { data: sizeData, isLoading } = useListSize(entry?.url); + const count = sizeData?.count || ''; return (
  • @@ -52,7 +53,13 @@ export function ListViewEntry({ className, entry, style }) { {entry.name} - {count} + + {isLoading ? ( + + ) : ( + count + )} + {entry.description && (
    From e75a25f7cb0b917efea4214504c7c1711852cbea Mon Sep 17 00:00:00 2001 From: Noah Manneschmidt Date: Fri, 24 Jan 2025 19:43:22 -0800 Subject: [PATCH 12/14] format list entry total --- src/detail-panels/lists/list-view.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/detail-panels/lists/list-view.jsx b/src/detail-panels/lists/list-view.jsx index d00cf8b3..88b1e5ef 100644 --- a/src/detail-panels/lists/list-view.jsx +++ b/src/detail-panels/lists/list-view.jsx @@ -31,7 +31,7 @@ export function ListView({ className, list }) { */ export function ListViewEntry({ className, entry, style }) { const { data: sizeData, isLoading } = useListSize(entry?.url); - const count = sizeData?.count || ''; + const count = sizeData?.count?.toLocaleString() || ''; return (
  • From a1bd248f9cf8c94c894bce286f82f5b63c1bfd0d Mon Sep 17 00:00:00 2001 From: Noah Manneschmidt Date: Sun, 26 Jan 2025 12:10:49 -0800 Subject: [PATCH 13/14] tune up request rate limiting --- package-lock.json | 9 +++++---- package.json | 2 +- src/api/lists.js | 23 +++++++++++++++-------- src/detail-panels/lists/lists.jsx | 8 ++++---- 4 files changed, 25 insertions(+), 17 deletions(-) diff --git a/package-lock.json b/package-lock.json index f59069b6..8a5d8477 100644 --- a/package-lock.json +++ b/package-lock.json @@ -21,7 +21,7 @@ "ag-grid-react": "^31.0.3", "fuse.js": "^7.0.0", "iso-web": "^1.0.6", - "p-queue": "8.1.0", + "p-queue": "npm:@nmann/p-queue@^8.1.1", "react": "^18.2.0", "react-dom": "^18.2.0", "react-router-dom": "^6.28.0" @@ -2514,9 +2514,10 @@ } }, "node_modules/p-queue": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/p-queue/-/p-queue-8.1.0.tgz", - "integrity": "sha512-mxLDbbGIBEXTJL0zEx8JIylaj3xQ7Z/7eEVjcF9fJX4DBiH9oqe+oahYnlKKxm0Ci9TlWTyhSHgygxMxjIB2jw==", + "name": "@nmann/p-queue", + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/@nmann/p-queue/-/p-queue-8.1.1.tgz", + "integrity": "sha512-hRJEsjHH5e5Vy6fkWbXMiFltbOXZfr1w7GXdThZNWXvQu+R/pJlGPDCyPUSDAXlObhFTMiEkAaH6y5gOEjzuFg==", "license": "MIT", "dependencies": { "eventemitter3": "^5.0.1", diff --git a/package.json b/package.json index d141910e..fd130001 100644 --- a/package.json +++ b/package.json @@ -27,7 +27,7 @@ "ag-grid-react": "^31.0.3", "fuse.js": "^7.0.0", "iso-web": "^1.0.6", - "p-queue": "8.1.0", + "p-queue": "npm:@nmann/p-queue@^8.1.1", "react": "^18.2.0", "react-dom": "^18.2.0", "react-router-dom": "^6.28.0" diff --git a/src/api/lists.js b/src/api/lists.js index a860b62b..f1fbbcf6 100644 --- a/src/api/lists.js +++ b/src/api/lists.js @@ -27,16 +27,18 @@ export function useList(handleOrDID) { * Look up the total number of lists to which a given handle/DID belongs * @param {string} handleOrDID */ -export function useListTotal(handleOrDID) { +export function useListCount(handleOrDID) { const profileQuery = useResolveHandleOrDid(handleOrDID); const shortHandle = profileQuery.data?.shortHandle; return useQuery({ enabled: !!shortHandle, queryKey: ['list-total', shortHandle], - queryFn: () => getListTotal(shortHandle), + queryFn: () => getListCount(shortHandle), }); } +const TWELVE_HOURS = 1000 * 60 * 60 * 12; + /** * Gets the size (length) of a given user list * @param {string} listUrl @@ -45,7 +47,9 @@ export function useListSize(listUrl) { return useQuery({ enabled: !!listUrl, queryKey: ['list-size', listUrl], - queryFn: () => getListSize(listUrl), + queryFn: ({ signal }) => getListSize(listUrl, signal), + staleTime: TWELVE_HOURS, + gcTime: TWELVE_HOURS, }); } @@ -85,7 +89,7 @@ async function getList(shortHandle, currentPage = 1) { * Gets the total number of lists to which a given handle belongs * @param {string} shortHandle */ -async function getListTotal(shortHandle) { +async function getListCount(shortHandle) { const handleURL = 'get-list/total/' + unwrapShortHandle(shortHandle); /** @type {{ data: { count: number; pages: number } }} */ const re = await fetchClearskyApi('v1', handleURL); @@ -95,13 +99,16 @@ async function getListTotal(shortHandle) { /** * Gets the size (length) of a given user list * @param {string} listUrl + * @param {AbortSignal} signal * @returns {Promise<{ count: number } | null>} null if response is a 400/404 */ -async function getListSize(listUrl) { +async function getListSize(listUrl, signal) { const apiUrl = unwrapClearskyURL( `/api/v1/anon/get-list/specific/total/${encodeURIComponent(listUrl)}` ); - const resp = await listSizeQueue.add(() => fetch(apiUrl), { + signal.throwIfAborted; + const resp = await listSizeQueue.add(() => fetch(apiUrl, { signal }), { + signal, throwOnTimeout: true, }); if (resp.ok) { @@ -117,11 +124,11 @@ async function getListSize(listUrl) { /** * create a queue where only one request can be in flight at a time, - * and at most 1 may be sent in any 500 millisecond interval + * and at most 1 may be sent in any 250 millisecond interval */ const listSizeQueue = new PQueue({ concurrency: 1, intervalCap: 1, - interval: 500, + interval: 200, timeout: 500, }); diff --git a/src/detail-panels/lists/lists.jsx b/src/detail-panels/lists/lists.jsx index 3cbd0245..94fad10e 100644 --- a/src/detail-panels/lists/lists.jsx +++ b/src/detail-panels/lists/lists.jsx @@ -1,13 +1,13 @@ // @ts-check -import { useState} from 'react'; +import { useState } from 'react'; import SearchIcon from '@mui/icons-material/Search'; import { Button, CircularProgress } from '@mui/material'; import { useSearchParams } from 'react-router-dom'; -import { useList, useListTotal } from '../../api/lists'; -import { ListView} from './list-view'; +import { useList, useListCount } from '../../api/lists'; +import { ListView } from './list-view'; import './lists.css'; import { SearchHeaderDebounced } from '../history/search-header'; @@ -22,7 +22,7 @@ export function Lists() { const { data, fetchNextPage, hasNextPage, isLoading, isFetching } = useList(shortHandle); const { data: totalData, isLoading: isLoadingTotal } = - useListTotal(shortHandle); + useListCount(shortHandle); const [searchParams, setSearchParams] = useSearchParams(); const [tick, setTick] = useState(0); From 48505f95c1a867339def15aee474f613af32887d Mon Sep 17 00:00:00 2001 From: Noah Manneschmidt Date: Sun, 26 Jan 2025 12:31:43 -0800 Subject: [PATCH 14/14] use existing "poor-man's virtualization" for lists --- src/common-components/progressive-render.jsx | 45 +++++++++++++++++++ .../block-panel-generic/list-view.jsx | 36 +++------------ src/detail-panels/lists/list-view.jsx | 13 +++--- 3 files changed, 57 insertions(+), 37 deletions(-) create mode 100644 src/common-components/progressive-render.jsx diff --git a/src/common-components/progressive-render.jsx b/src/common-components/progressive-render.jsx new file mode 100644 index 00000000..916fec8f --- /dev/null +++ b/src/common-components/progressive-render.jsx @@ -0,0 +1,45 @@ +// @ts-check +import { useState, cloneElement } from 'react'; +import { Visible } from './visible'; + +const INITIAL_SIZE = 20; +const GROW_BLOCK_SIZE = 29; + +/** + * @template ItemType + * @param {{ items: Array, renderItem(item: ItemType): import('react').ReactElement }} props + * Given a list of items, only renders the first 20 by default, + * and then more whenever the last item is close to being on screen + */ +export function ProgressiveRender(props) { + const [listSize, setListSize] = useState(INITIAL_SIZE); + const showSize = Math.min(props.items.length, listSize); + + return ( + <> + {props.items.slice(0, showSize).map((item, index) => { + const entry = cloneElement(props.renderItem(item), { key: index }); + + return index < showSize - 1 ? ( + entry + ) : ( + + {entry} + + ); + })} + + ); + + function handleBottomVisible() { + const incrementListSize = listSize + GROW_BLOCK_SIZE; + setListSize(incrementListSize); + if (incrementListSize > props.items.length) { + // TODO: control fetch more from here? + } + } +} diff --git a/src/detail-panels/block-panel-generic/list-view.jsx b/src/detail-panels/block-panel-generic/list-view.jsx index 7af8aa6f..b02c2979 100644 --- a/src/detail-panels/block-panel-generic/list-view.jsx +++ b/src/detail-panels/block-panel-generic/list-view.jsx @@ -1,50 +1,24 @@ // @ts-check /// import { FormatTimestamp } from '../../common-components/format-timestamp'; -import { Visible } from '../../common-components/visible'; -import { useState } from 'react'; +import { ProgressiveRender } from '../../common-components/progressive-render'; import { AccountShortEntry } from '../../common-components/account-short-entry'; import { localise } from '../../localisation'; -const INITIAL_SIZE = 20; -const GROW_BLOCK_SIZE = 29; - /** * @param {{ * blocklist: (BlockedByRecord | { did: string; blocked_date: string })[]; * }} _ */ export function ListView({ blocklist }) { - const [listSize, setListSize] = useState(INITIAL_SIZE); - const showSize = Math.min(blocklist.length, listSize); - return (
      - {blocklist.slice(0, showSize).map((block, index) => { - const entry = ; - - return index < showSize - 1 ? ( - entry - ) : ( - - {entry} - - ); - })} + } + />
    ); - - function handleBottomVisible() { - const incrementListSize = listSize + GROW_BLOCK_SIZE; - setListSize(incrementListSize); - if (incrementListSize > blocklist.length) { - // TODO: fetch more - } - } } /** diff --git a/src/detail-panels/lists/list-view.jsx b/src/detail-panels/lists/list-view.jsx index 88b1e5ef..e5e42734 100644 --- a/src/detail-panels/lists/list-view.jsx +++ b/src/detail-panels/lists/list-view.jsx @@ -5,6 +5,7 @@ import { AccountShortEntry } from '../../common-components/account-short-entry'; import { FormatTimestamp } from '../../common-components/format-timestamp'; import { useListSize } from '../../api/lists'; import './list-view.css'; +import { ProgressiveRender } from '../../common-components/progressive-render'; /** * @param {{ @@ -15,9 +16,10 @@ import './list-view.css'; export function ListView({ className, list }) { return (
      - {(list || []).map((entry, i) => ( - - ))} + } + />
    ); } @@ -25,11 +27,10 @@ export function ListView({ className, list }) { /** * @param {{ * className?: string, - * entry: AccountListEntry, - * style:any + * entry: AccountListEntry * }} _ */ -export function ListViewEntry({ className, entry, style }) { +export function ListViewEntry({ className, entry }) { const { data: sizeData, isLoading } = useListSize(entry?.url); const count = sizeData?.count?.toLocaleString() || '';