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

reposted by indicators

rimar1337 78b79fd1 bd1ce421

+58 -15
+33 -9
src/components/InfiniteCustomFeed.tsx
··· 2 //import { useInView } from "react-intersection-observer"; 3 import { UniversalPostRendererATURILoader } from "~/components/UniversalPostRenderer"; 4 import { useAuth } from "~/providers/PassAuthProvider"; 5 - import { useQueryArbitrary, useQueryIdentity, useInfiniteQueryFeedSkeleton } from "~/utils/useQuery"; 6 7 interface InfiniteCustomFeedProps { 8 feedUri: string; ··· 10 feedServiceDid?: string; 11 } 12 13 - export function InfiniteCustomFeed({ feedUri, pdsUrl, feedServiceDid }: InfiniteCustomFeedProps) { 14 const { agent, authed } = useAuth(); 15 - 16 // const identityresultmaybe = useQueryIdentity(agent?.did); 17 // const identity = identityresultmaybe?.data; 18 // const feedGenGetRecordQuery = useQueryArbitrary(feedUri); ··· 46 } 47 48 if (isError) { 49 - return <div className="p-4 text-center text-red-500">Error: {error.message}</div>; 50 } 51 52 - const allPosts = data?.pages.flatMap((page) => {if (page) return page.feed}) ?? []; 53 54 if (!allPosts || typeof allPosts !== "object" || allPosts.length === 0) { 55 - return <div className="p-4 text-center text-gray-500">No posts in this feed.</div>; 56 } 57 58 return ( 59 <> 60 {allPosts.map((item, i) => { 61 - if (item) return ( 62 - <UniversalPostRendererATURILoader key={item.post || i} atUri={item.post} /> 63 - )})} 64 {/* allPosts?: {allPosts ? "true" : "false"} 65 hasNextPage?: {hasNextPage ? "true" : "false"} 66 isFetchingNextPage?: {isFetchingNextPage ? "true" : "false"} */}
··· 2 //import { useInView } from "react-intersection-observer"; 3 import { UniversalPostRendererATURILoader } from "~/components/UniversalPostRenderer"; 4 import { useAuth } from "~/providers/PassAuthProvider"; 5 + import { 6 + useQueryArbitrary, 7 + useQueryIdentity, 8 + useInfiniteQueryFeedSkeleton, 9 + } from "~/utils/useQuery"; 10 11 interface InfiniteCustomFeedProps { 12 feedUri: string; ··· 14 feedServiceDid?: string; 15 } 16 17 + export function InfiniteCustomFeed({ 18 + feedUri, 19 + pdsUrl, 20 + feedServiceDid, 21 + }: InfiniteCustomFeedProps) { 22 const { agent, authed } = useAuth(); 23 + 24 // const identityresultmaybe = useQueryIdentity(agent?.did); 25 // const identity = identityresultmaybe?.data; 26 // const feedGenGetRecordQuery = useQueryArbitrary(feedUri); ··· 54 } 55 56 if (isError) { 57 + return ( 58 + <div className="p-4 text-center text-red-500">Error: {error.message}</div> 59 + ); 60 } 61 62 + const allPosts = 63 + data?.pages.flatMap((page) => { 64 + if (page) return page.feed; 65 + }) ?? []; 66 67 if (!allPosts || typeof allPosts !== "object" || allPosts.length === 0) { 68 + return ( 69 + <div className="p-4 text-center text-gray-500"> 70 + No posts in this feed. 71 + </div> 72 + ); 73 } 74 75 return ( 76 <> 77 {allPosts.map((item, i) => { 78 + if (item) 79 + return ( 80 + <UniversalPostRendererATURILoader 81 + key={item.post || i} 82 + atUri={item.post} 83 + feedviewpost={true} 84 + repostedby={!!item.reason?.$type && (item.reason as any)?.repost} 85 + /> 86 + ); 87 + })} 88 {/* allPosts?: {allPosts ? "true" : "false"} 89 hasNextPage?: {hasNextPage ? "true" : "false"} 90 isFetchingNextPage?: {isFetchingNextPage ? "true" : "false"} */}
+25 -6
src/components/UniversalPostRenderer.tsx
··· 25 topReplyLine?: boolean; 26 bottomBorder?: boolean; 27 feedviewpost?: boolean; 28 } 29 30 // export async function cachedGetRecord({ ··· 128 topReplyLine, 129 bottomBorder = true, 130 feedviewpost = false, 131 }: UniversalPostRendererATURILoaderProps) { 132 console.log("atUri", atUri); 133 //const { get, set } = usePersistentStore(); ··· 381 // }); 382 // } 383 // }; 384 385 return ( 386 <UniversalPostRendererRawRecordShim ··· 396 topReplyLine={topReplyLine} 397 bottomBorder={bottomBorder} 398 feedviewpost={feedviewpost} 399 /> 400 ); 401 } ··· 413 topReplyLine = false, 414 bottomBorder = true, 415 feedviewpost = false, 416 }: { 417 postRecord: any; 418 profileRecord: any; ··· 426 topReplyLine?: boolean; 427 bottomBorder?: boolean; 428 feedviewpost?: boolean; 429 }) { 430 console.log(`received aturi: ${aturi} of post content: ${postRecord}`); 431 const navigate = useNavigate(); ··· 583 feedviewpost ? feedviewpostreplydid : undefined 584 ); 585 const feedviewpostreplyhandle = replyhookvalue?.data?.handle; 586 return ( 587 <> 588 {/* <p> ··· 616 bottomBorder={bottomBorder} 617 //extraOptionalItemInfo={{reply: postRecord?.value?.reply as AppBskyFeedDefs.ReplyRef, post: fakepost}} 618 feedviewpostreplyhandle={feedviewpostreplyhandle} 619 /> 620 </> 621 ); ··· 1058 bottomBorder = true, 1059 feedviewpostreplyhandle, 1060 depth = 0, 1061 }: { 1062 post: PostView; 1063 // optional for now because i havent ported every use to this yet ··· 1076 bottomBorder?: boolean; 1077 feedviewpostreplyhandle?: string; 1078 depth?: number; 1079 }) { 1080 const navigate = useNavigate(); 1081 const [hasRetweeted, setHasRetweeted] = useState<Boolean>( ··· 1124 } 1125 }; 1126 1127 - const isRepost = extraOptionalItemInfo 1128 ? AppBskyFeedDefs.isReasonRepost(extraOptionalItemInfo.reason) 1129 ? extraOptionalItemInfo.reason?.by.displayName 1130 : undefined ··· 1190 }} 1191 className="text-gray-500 dark:text-gray-400" 1192 > 1193 - <MdiRepost /> Reposted by {isRepost}{" "} 1194 </div> 1195 )} 1196 {!isQuote && ( ··· 1292 maxWidth: `calc(100% - ${!expanded ? (isQuote ? 26 : 0) : 54}px)`, 1293 width: `calc(100% - ${!expanded ? (isQuote ? 26 : 0) : 54}px)`, 1294 marginLeft: !expanded ? (isQuote ? 26 : 0) : 54, 1295 - marginBottom: !expanded ? 4 : 0, 1296 }} 1297 > 1298 <div ··· 1308 gap: expanded ? 0 : 6, 1309 alignItems: expanded ? "flex-start" : "center", 1310 flexDirection: expanded ? "column" : "row", 1311 - height: expanded ? 48 : "1rem", 1312 }} 1313 > 1314 <span ··· 1395 }} 1396 className="text-gray-500 dark:text-gray-400" 1397 > 1398 - <MdiReply /> Reply to {feedviewpostreplyhandle} 1399 </div> 1400 )} 1401 <div ··· 1428 ) : null} 1429 {post.embed && depth > 0 && ( 1430 <> 1431 - <div className="border-gray-300 dark:border-gray-600 p-3 rounded-xl border italic text-gray-400"> 1432 (there is an embed here thats too deep to render) 1433 </div> 1434 </>
··· 25 topReplyLine?: boolean; 26 bottomBorder?: boolean; 27 feedviewpost?: boolean; 28 + repostedby?: string; 29 } 30 31 // export async function cachedGetRecord({ ··· 129 topReplyLine, 130 bottomBorder = true, 131 feedviewpost = false, 132 + repostedby, 133 }: UniversalPostRendererATURILoaderProps) { 134 console.log("atUri", atUri); 135 //const { get, set } = usePersistentStore(); ··· 383 // }); 384 // } 385 // }; 386 + if (!postQuery?.value) { 387 + // deleted post more often than a non-resolvable post 388 + return (<></>) 389 + } 390 391 return ( 392 <UniversalPostRendererRawRecordShim ··· 402 topReplyLine={topReplyLine} 403 bottomBorder={bottomBorder} 404 feedviewpost={feedviewpost} 405 + repostedby={repostedby} 406 /> 407 ); 408 } ··· 420 topReplyLine = false, 421 bottomBorder = true, 422 feedviewpost = false, 423 + repostedby, 424 }: { 425 postRecord: any; 426 profileRecord: any; ··· 434 topReplyLine?: boolean; 435 bottomBorder?: boolean; 436 feedviewpost?: boolean; 437 + repostedby?: string; 438 }) { 439 console.log(`received aturi: ${aturi} of post content: ${postRecord}`); 440 const navigate = useNavigate(); ··· 592 feedviewpost ? feedviewpostreplydid : undefined 593 ); 594 const feedviewpostreplyhandle = replyhookvalue?.data?.handle; 595 + 596 + 597 + const aturirepostbydid = repostedby ? new AtUri(repostedby).host : undefined 598 + const repostedbyhookvalue = useQueryIdentity( 599 + repostedby ? aturirepostbydid : undefined 600 + ); 601 + const feedviewpostrepostedbyhandle = repostedbyhookvalue?.data?.handle; 602 return ( 603 <> 604 {/* <p> ··· 632 bottomBorder={bottomBorder} 633 //extraOptionalItemInfo={{reply: postRecord?.value?.reply as AppBskyFeedDefs.ReplyRef, post: fakepost}} 634 feedviewpostreplyhandle={feedviewpostreplyhandle} 635 + repostedby={feedviewpostrepostedbyhandle} 636 /> 637 </> 638 ); ··· 1075 bottomBorder = true, 1076 feedviewpostreplyhandle, 1077 depth = 0, 1078 + repostedby, 1079 }: { 1080 post: PostView; 1081 // optional for now because i havent ported every use to this yet ··· 1094 bottomBorder?: boolean; 1095 feedviewpostreplyhandle?: string; 1096 depth?: number; 1097 + repostedby?: string; 1098 }) { 1099 const navigate = useNavigate(); 1100 const [hasRetweeted, setHasRetweeted] = useState<Boolean>( ··· 1143 } 1144 }; 1145 1146 + const isRepost = repostedby ? repostedby : extraOptionalItemInfo 1147 ? AppBskyFeedDefs.isReasonRepost(extraOptionalItemInfo.reason) 1148 ? extraOptionalItemInfo.reason?.by.displayName 1149 : undefined ··· 1209 }} 1210 className="text-gray-500 dark:text-gray-400" 1211 > 1212 + <MdiRepost /> Reposted by @{isRepost}{" "} 1213 </div> 1214 )} 1215 {!isQuote && ( ··· 1311 maxWidth: `calc(100% - ${!expanded ? (isQuote ? 26 : 0) : 54}px)`, 1312 width: `calc(100% - ${!expanded ? (isQuote ? 26 : 0) : 54}px)`, 1313 marginLeft: !expanded ? (isQuote ? 26 : 0) : 54, 1314 + marginBottom: !expanded ? 4 : 6, 1315 }} 1316 > 1317 <div ··· 1327 gap: expanded ? 0 : 6, 1328 alignItems: expanded ? "flex-start" : "center", 1329 flexDirection: expanded ? "column" : "row", 1330 + height: expanded ? 42 : "1rem", 1331 }} 1332 > 1333 <span ··· 1414 }} 1415 className="text-gray-500 dark:text-gray-400" 1416 > 1417 + <MdiReply /> Reply to @{feedviewpostreplyhandle} 1418 </div> 1419 )} 1420 <div ··· 1447 ) : null} 1448 {post.embed && depth > 0 && ( 1449 <> 1450 + <div className="border-gray-300 dark:border-gray-600 p-3 rounded-xl border italic text-gray-400 text-[14px]"> 1451 (there is an embed here thats too deep to render) 1452 </div> 1453 </>