an independent Bluesky client using Constellation, PDS Queries, and other services reddwarf.app
frontend spa bluesky reddwarf microcosm client app
99
fork

Configure Feed

Select the types of activity you want to include in your feed.

attempt to prevent feed corruption

rimar1337 78e2b52c 689f5ca0

+35 -8
+32 -6
src/components/InfiniteCustomFeed.tsx
··· 1 + import { useQueryClient } from "@tanstack/react-query"; 1 2 import * as React from "react"; 2 3 3 4 //import { useInView } from "react-intersection-observer"; ··· 37 38 isFetchingNextPage, 38 39 refetch, 39 40 isRefetching, 41 + queryKey, 40 42 } = useInfiniteQueryFeedSkeleton({ 41 43 feedUri: feedUri, 42 44 agent: agent ?? undefined, ··· 44 46 pdsUrl: pdsUrl, 45 47 feedServiceDid: feedServiceDid, 46 48 }); 49 + const queryClient = useQueryClient(); 50 + 47 51 48 52 const handleRefresh = () => { 53 + queryClient.removeQueries({queryKey: queryKey}); 54 + //queryClient.invalidateQueries(["infinite-feed", feedUri] as const); 49 55 refetch(); 50 56 }; 51 57 58 + const allPosts = React.useMemo(() => { 59 + const flattenedPosts = data?.pages.flatMap((page) => page?.feed) ?? []; 60 + 61 + const seenUris = new Set<string>(); 62 + 63 + return flattenedPosts.filter((item) => { 64 + if (!item?.post) return false; 65 + 66 + if (seenUris.has(item.post)) { 67 + return false; 68 + } 69 + 70 + seenUris.add(item.post); 71 + 72 + return true; 73 + }); 74 + }, [data]); 75 + 52 76 //const { ref, inView } = useInView(); 53 77 54 78 // React.useEffect(() => { ··· 67 91 ); 68 92 } 69 93 70 - const allPosts = 71 - data?.pages.flatMap((page) => { 72 - if (page) return page.feed; 73 - }) ?? []; 94 + // const allPosts = 95 + // data?.pages.flatMap((page) => { 96 + // if (page) return page.feed; 97 + // }) ?? []; 74 98 75 99 if (!allPosts || typeof allPosts !== "object" || allPosts.length === 0) { 76 100 return ( ··· 116 140 className="sticky lg:bottom-4 bottom-22 ml-4 w-[42px] h-[42px] z-10 bg-gray-200 dark:bg-gray-800 hover:bg-gray-300 dark:hover:bg-gray-700 text-gray-50 p-[9px] rounded-full shadow-lg transition-transform duration-200 ease-in-out hover:scale-110 disabled:dark:bg-gray-900 disabled:bg-gray-100 disabled:cursor-not-allowed" 117 141 aria-label="Refresh feed" 118 142 > 119 - <RefreshIcon className={`h-6 w-6 text-gray-600 dark:text-gray-400 ${isRefetching && "animate-spin"}`} /> 143 + <RefreshIcon 144 + className={`h-6 w-6 text-gray-600 dark:text-gray-400 ${isRefetching && "animate-spin"}`} 145 + /> 120 146 </button> 121 147 </> 122 148 ); ··· 139 165 d="M20 11A8.1 8.1 0 0 0 4.5 9M4 5v4h4m-4 4a8.1 8.1 0 0 0 15.5 2m.5 4v-4h-4" 140 166 ></path> 141 167 </svg> 142 - ); 168 + );
+1
src/routes/index.tsx
··· 418 418 419 419 {isReadyForAuthedFeed || isReadyForUnauthedFeed ? ( 420 420 <InfiniteCustomFeed 421 + key={selectedFeed!} 421 422 feedUri={selectedFeed!} 422 423 pdsUrl={identity?.pds} 423 424 feedServiceDid={feedServiceDid}
+2 -2
src/utils/useQuery.ts
··· 615 615 }) { 616 616 const { queryKey, queryFn } = constructInfiniteFeedSkeletonQuery(options); 617 617 618 - return useInfiniteQuery({ 618 + return {...useInfiniteQuery({ 619 619 queryKey, 620 620 queryFn, 621 621 initialPageParam: undefined as never, ··· 623 623 staleTime: Infinity, 624 624 refetchOnWindowFocus: false, 625 625 enabled: !!options.feedUri && (options.isAuthed ? !!options.agent && !!options.pdsUrl && !!options.feedServiceDid : true), 626 - }); 626 + }), queryKey: queryKey}; 627 627 } 628 628 629 629