👁️
5
fork

Configure Feed

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

filter invalid records from profile page

+22 -14
+4 -4
src/lib/atproto-client.ts
··· 245 245 for (const record of json.records) { 246 246 const result = safeParse(schema, record.value); 247 247 if (!result.ok) { 248 - return { 249 - success: false, 250 - error: new Error(result.message), 251 - }; 248 + console.warn( 249 + `Skipping malformed ${entityName} record ${record.uri}: ${result.message}`, 250 + ); 251 + continue; 252 252 } 253 253 validatedRecords.push({ 254 254 uri: record.uri as AtUri,
+18 -10
src/routes/profile/$did/index.tsx
··· 1 1 import type { Did } from "@atcute/lexicons"; 2 - import { 3 - useInfiniteQuery, 4 - useQuery, 5 - useSuspenseInfiniteQuery, 6 - } from "@tanstack/react-query"; 2 + import { useInfiniteQuery, useQuery } from "@tanstack/react-query"; 7 3 import { createFileRoute, Link } from "@tanstack/react-router"; 8 4 import { Plus } from "lucide-react"; 9 5 import { useMemo } from "react"; ··· 99 95 const search = Route.useSearch(); 100 96 const navigate = Route.useNavigate(); 101 97 const { session } = useAuth(); 102 - const { data: decksData } = useSuspenseInfiniteQuery( 98 + const { data: decksData, isLoading: decksLoading } = useInfiniteQuery( 103 99 listUserDecksQueryOptions(did as Did), 104 100 ); 105 - const { data: listsData } = useInfiniteQuery( 101 + const { data: listsData, isLoading: listsLoading } = useInfiniteQuery( 106 102 listUserCollectionListsQueryOptions(did as Did), 107 103 ); 108 104 const { data: didDocument } = useQuery(didDocumentQueryOptions(did as Did)); ··· 110 106 111 107 const handle = extractHandle(didDocument ?? null); 112 108 const isOwner = session?.info.sub === did; 113 - const decks = decksData.pages.flatMap((p) => p.records); 109 + const decks = decksData?.pages.flatMap((p) => p.records) ?? []; 114 110 const lists = listsData?.pages.flatMap((p) => p.records) ?? []; 115 111 116 112 // Get unique formats for filter dropdown ··· 210 206 <h2 className="text-2xl font-bold text-gray-900 dark:text-white mb-4"> 211 207 Decks 212 208 </h2> 213 - {decks.length === 0 ? ( 209 + {decksLoading ? ( 210 + <div className="text-center py-8 bg-gray-50 dark:bg-slate-800 rounded-lg"> 211 + <p className="text-gray-600 dark:text-gray-400"> 212 + Loading decklists... 213 + </p> 214 + </div> 215 + ) : decks.length === 0 ? ( 214 216 <div className="text-center py-8 bg-gray-50 dark:bg-slate-800 rounded-lg"> 215 217 <p className="text-gray-600 dark:text-gray-400 mb-4"> 216 218 {isOwner ? "No decklists yet" : "No decklists"} ··· 278 280 </button> 279 281 )} 280 282 </div> 281 - {lists.length === 0 ? ( 283 + {listsLoading ? ( 284 + <div className="text-center py-8 bg-gray-50 dark:bg-slate-800 rounded-lg"> 285 + <p className="text-gray-600 dark:text-gray-400"> 286 + Loading lists... 287 + </p> 288 + </div> 289 + ) : lists.length === 0 ? ( 282 290 <div className="text-center py-8 bg-gray-50 dark:bg-slate-800 rounded-lg"> 283 291 <p className="text-gray-600 dark:text-gray-400"> 284 292 {isOwner ? "No lists yet" : "No lists"}