From 882a7716d7e06624fff189bdcdb0cb846b756aa5 Mon Sep 17 00:00:00 2001 From: Pouria Delfanazari Date: Fri, 3 Oct 2025 16:12:27 -0700 Subject: [PATCH 1/7] refactor: move suspense up to card actions --- .../features/cards/components/urlCard/UrlCard.tsx | 12 +++++++++++- .../components/urlCardActions/UrlCardActions.tsx | 2 +- src/webapp/next-env.d.ts | 1 + 3 files changed, 13 insertions(+), 2 deletions(-) diff --git a/src/webapp/features/cards/components/urlCard/UrlCard.tsx b/src/webapp/features/cards/components/urlCard/UrlCard.tsx index 20eca60e..b067390c 100644 --- a/src/webapp/features/cards/components/urlCard/UrlCard.tsx +++ b/src/webapp/features/cards/components/urlCard/UrlCard.tsx @@ -8,6 +8,7 @@ import { Group, Anchor, AspectRatio, + Skeleton, } from '@mantine/core'; import Link from 'next/link'; import UrlCardActions from '../urlCardActions/UrlCardActions'; @@ -69,7 +70,16 @@ export default function UrlCard(props: Props) { )} - + + + + + + + } + > /// +/// // NOTE: This file should not be edited // see https://nextjs.org/docs/app/api-reference/config/typescript for more information. -- 2.51.2 From fe58329e3eadf44686de26461be1b683a9884d78 Mon Sep 17 00:00:00 2001 From: Pouria Delfanazari Date: Fri, 3 Oct 2025 16:50:25 -0700 Subject: [PATCH 2/7] feat: infinite scrolling on cards, feeds, collections --- .../infiniteScroll/InfiniteScroll.tsx | 43 ++++++++++++ .../cardsContainer/CardsContainer.tsx | 65 +++++++++---------- .../CollectionsContainer.tsx | 30 ++++----- .../myFeedContainer/MyFeedContainer.tsx | 43 ++++++------ 4 files changed, 108 insertions(+), 73 deletions(-) create mode 100644 src/webapp/components/contentDisplay/infiniteScroll/InfiniteScroll.tsx diff --git a/src/webapp/components/contentDisplay/infiniteScroll/InfiniteScroll.tsx b/src/webapp/components/contentDisplay/infiniteScroll/InfiniteScroll.tsx new file mode 100644 index 00000000..1d6c3ad0 --- /dev/null +++ b/src/webapp/components/contentDisplay/infiniteScroll/InfiniteScroll.tsx @@ -0,0 +1,43 @@ +'use client'; + +import { ReactNode, useEffect, startTransition } from 'react'; +import { Center, Button, Stack } from '@mantine/core'; +import { useInViewport } from '@mantine/hooks'; + +interface Props { + children: ReactNode; + dataLength: number; + hasMore: boolean; + isInitialLoading: boolean; + isLoading: boolean; + loadMore: () => void; + loader?: ReactNode; + manualLoadButton?: boolean; +} + +export default function InfiniteScroll(props: Props) { + const { ref, inViewport } = useInViewport(); + + useEffect(() => { + startTransition(() => { + if (inViewport && props.hasMore && !props.isLoading) { + props.loadMore(); + } + }); + }, [inViewport, props.hasMore, props.isLoading, props.loadMore]); + + return ( + + {props.children} + {props.isLoading && props.loader} + +
+ {!props.isLoading && props.hasMore && props.manualLoadButton && ( + + )} +
+
+ ); +} diff --git a/src/webapp/features/cards/containers/cardsContainer/CardsContainer.tsx b/src/webapp/features/cards/containers/cardsContainer/CardsContainer.tsx index 37631fe5..b5cee771 100644 --- a/src/webapp/features/cards/containers/cardsContainer/CardsContainer.tsx +++ b/src/webapp/features/cards/containers/cardsContainer/CardsContainer.tsx @@ -1,13 +1,13 @@ 'use client'; -import { Container, Grid, Stack, Button, Text, Center } from '@mantine/core'; +import { Center, Container, Grid, Loader, Stack } from '@mantine/core'; import useCards from '../../lib/queries/useCards'; import UrlCard from '@/features/cards/components/urlCard/UrlCard'; import CardsContainerError from './Error.CardsContainer'; import CardsContainerSkeleton from './Skeleton.CardsContainer'; -import { Fragment, useState } from 'react'; import ProfileEmptyTab from '@/features/profile/components/profileEmptyTab/ProfileEmptyTab'; import { FaRegNoteSticky } from 'react-icons/fa6'; +import InfiniteScroll from '@/components/contentDisplay/infiniteScroll/InfiniteScroll'; interface Props { handle: string; @@ -43,39 +43,34 @@ export default function CardsContainer(props: Props) { return ( - - - - {allCards.map((card) => ( - - - - ))} - - - {hasNextPage && ( -
- -
- )} -
-
+ + + + } + > + + {allCards.map((card) => ( + + + + ))} + +
); } diff --git a/src/webapp/features/collections/containers/collectionsContainer/CollectionsContainer.tsx b/src/webapp/features/collections/containers/collectionsContainer/CollectionsContainer.tsx index b7ecb4c5..5b9be3b4 100644 --- a/src/webapp/features/collections/containers/collectionsContainer/CollectionsContainer.tsx +++ b/src/webapp/features/collections/containers/collectionsContainer/CollectionsContainer.tsx @@ -1,12 +1,13 @@ 'use client'; -import { Button, Container, Stack, SimpleGrid, Center } from '@mantine/core'; +import { Button, Container, Stack, SimpleGrid } from '@mantine/core'; import useCollections from '../../lib/queries/useCollections'; import CollectionCard from '../../components/collectionCard/CollectionCard'; import CreateCollectionDrawer from '../../components/createCollectionDrawer/CreateCollectionDrawer'; import { useState } from 'react'; import ProfileEmptyTab from '@/features/profile/components/profileEmptyTab/ProfileEmptyTab'; import { BiCollection } from 'react-icons/bi'; +import InfiniteLoadTrigger from '@/components/contentDisplay/infiniteScroll/InfiniteScroll'; interface Props { handle: string; @@ -32,28 +33,21 @@ export default function CollectionsContainer(props: Props) { return ( - + Loading...} // replace with your loader component if you want + > {collections.map((collection) => ( ))} - - {hasNextPage && ( -
- -
- )} -
+
) : ( - - - {allActivities.map((item, i) => ( - - ))} + + + + } + > + + + {allActivities.map((item) => ( + + ))} + - - {hasNextPage && ( -
- -
- )} -
+ )}
-- 2.51.2 From 7141c31d43a1431a8934665efc3f2a247a2e7e86 Mon Sep 17 00:00:00 2001 From: Pouria Delfanazari Date: Fri, 3 Oct 2025 16:53:56 -0700 Subject: [PATCH 3/7] feat: use default loader on feed container --- .../feeds/containers/myFeedContainer/MyFeedContainer.tsx | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/webapp/features/feeds/containers/myFeedContainer/MyFeedContainer.tsx b/src/webapp/features/feeds/containers/myFeedContainer/MyFeedContainer.tsx index 04e0117a..48595754 100644 --- a/src/webapp/features/feeds/containers/myFeedContainer/MyFeedContainer.tsx +++ b/src/webapp/features/feeds/containers/myFeedContainer/MyFeedContainer.tsx @@ -2,11 +2,10 @@ import useMyFeed from '@/features/feeds/lib/queries/useMyFeed'; import FeedItem from '@/features/feeds/components/feedItem/FeedItem'; -import { Stack, Title, Text, Center, Container } from '@mantine/core'; +import { Stack, Title, Text, Center, Container, Loader } from '@mantine/core'; import MyFeedContainerSkeleton from './Skeleton.MyFeedContainer'; import MyFeedContainerError from './Error.MyFeedContainer'; import InfiniteScroll from '@/components/contentDisplay/infiniteScroll/InfiniteScroll'; -import FeedItemSkeleton from '../../components/feedItem/Skeleton.FeedItem'; export default function MyFeedContainer() { const { @@ -49,9 +48,9 @@ export default function MyFeedContainer() { loadMore={fetchNextPage} manualLoadButton={false} loader={ - - - +
+ +
} > -- 2.51.2 From 3d00e8b70753cc02468ca5e19d69d192c6ae49dc Mon Sep 17 00:00:00 2001 From: Pouria Delfanazari Date: Fri, 3 Oct 2025 17:04:56 -0700 Subject: [PATCH 4/7] feat: decrease threshold for infinite scroll trigger --- .../infiniteScroll/InfiniteScroll.tsx | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/webapp/components/contentDisplay/infiniteScroll/InfiniteScroll.tsx b/src/webapp/components/contentDisplay/infiniteScroll/InfiniteScroll.tsx index 1d6c3ad0..c7e2858a 100644 --- a/src/webapp/components/contentDisplay/infiniteScroll/InfiniteScroll.tsx +++ b/src/webapp/components/contentDisplay/infiniteScroll/InfiniteScroll.tsx @@ -1,8 +1,8 @@ 'use client'; -import { ReactNode, useEffect, startTransition } from 'react'; +import { ReactNode, useEffect, startTransition, useRef } from 'react'; import { Center, Button, Stack } from '@mantine/core'; -import { useInViewport } from '@mantine/hooks'; +import { useIntersection } from '@mantine/hooks'; interface Props { children: ReactNode; @@ -16,15 +16,19 @@ interface Props { } export default function InfiniteScroll(props: Props) { - const { ref, inViewport } = useInViewport(); + const containerRef = useRef(null); + const { ref, entry } = useIntersection({ + root: containerRef.current, + threshold: 0, + }); useEffect(() => { startTransition(() => { - if (inViewport && props.hasMore && !props.isLoading) { + if (entry?.isIntersecting && props.hasMore && !props.isLoading) { props.loadMore(); } }); - }, [inViewport, props.hasMore, props.isLoading, props.loadMore]); + }, [entry?.isIntersecting, props.hasMore, props.isLoading, props.loadMore]); return ( -- 2.51.2 From c51bd5b9e1266c8e8ff1a980c32812ad0b252f1c Mon Sep 17 00:00:00 2001 From: Pouria Delfanazari Date: Mon, 6 Oct 2025 10:08:06 -0700 Subject: [PATCH 5/7] fix: (temp) incorrect author check on url card --- .../features/cards/components/urlCardActions/UrlCardActions.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/webapp/features/cards/components/urlCardActions/UrlCardActions.tsx b/src/webapp/features/cards/components/urlCardActions/UrlCardActions.tsx index be75bd07..102d84c4 100644 --- a/src/webapp/features/cards/components/urlCardActions/UrlCardActions.tsx +++ b/src/webapp/features/cards/components/urlCardActions/UrlCardActions.tsx @@ -27,7 +27,7 @@ export default function UrlCardActions(props: Props) { // assume the current user is the card owner if authorHandle isn't passed const isAuthor = props.authorHandle ? user?.handle === props.authorHandle - : false; + : true; const [showEditNoteModal, setShowEditNoteModal] = useState(false); const [showRemoveFromCollectionModal, setShowRemoveFromCollectionModal] = useState(false); -- 2.51.2 From 291b927f1b7073351ffdafde54948df996b348b2 Mon Sep 17 00:00:00 2001 From: Pouria Delfanazari Date: Mon, 6 Oct 2025 10:27:45 -0700 Subject: [PATCH 6/7] fix: existing collection link on collection selector --- .../cards/components/addCardToModal/CardToBeAddedPreview.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/webapp/features/cards/components/addCardToModal/CardToBeAddedPreview.tsx b/src/webapp/features/cards/components/addCardToModal/CardToBeAddedPreview.tsx index 9ef53060..501e074f 100644 --- a/src/webapp/features/cards/components/addCardToModal/CardToBeAddedPreview.tsx +++ b/src/webapp/features/cards/components/addCardToModal/CardToBeAddedPreview.tsx @@ -16,6 +16,7 @@ import { BiCollection } from 'react-icons/bi'; import { LuLibrary } from 'react-icons/lu'; import { getDomain } from '@/lib/utils/link'; import useMyProfile from '@/features/profile/lib/queries/useMyProfile'; +import { getRecordKey } from '@/lib/utils/atproto'; interface Props { cardId: string; @@ -95,7 +96,7 @@ export default function CardToBeAddedPreview(props: Props) { Date: Wed, 8 Oct 2025 13:40:51 -0700 Subject: [PATCH 7/7] fix: outdated navbar padding --- src/webapp/components/navigation/navbar/Navbar.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/webapp/components/navigation/navbar/Navbar.tsx b/src/webapp/components/navigation/navbar/Navbar.tsx index a24a5371..f095344f 100644 --- a/src/webapp/components/navigation/navbar/Navbar.tsx +++ b/src/webapp/components/navigation/navbar/Navbar.tsx @@ -30,7 +30,7 @@ export default function Navbar() { const { data: profile } = useMyProfile(); return ( - + Semble logo -- 2.51.2