an appview-less Bluesky client using Constellation and PDS Queries reddwarf.app
frontend spa bluesky reddwarf microcosm

for real this time

rimar1337 fe5744ad 2f2f25fa

Changed files
+38 -24
src
components
routes
utils
+4 -1
src/components/UniversalPostRenderer.tsx
··· 5 import * as React from "react"; 6 import { type SVGProps } from "react"; 7 8 - import { composerAtom, likedPostsAtom } from "~/utils/atoms"; 9 import { useHydratedEmbed } from "~/utils/useHydrated"; 10 import { 11 useQueryConstellation, ··· 401 // path: ".reply.parent.uri", 402 // }); 403 404 const infinitequeryresults = useInfiniteQuery({ 405 ...yknowIReallyHateThisButWhateverGuardedConstructConstellationInfiniteQueryLinks( 406 { 407 method: "/links", 408 target: atUri, 409 collection: "app.bsky.feed.post",
··· 5 import * as React from "react"; 6 import { type SVGProps } from "react"; 7 8 + import { composerAtom, constellationURLAtom, likedPostsAtom } from "~/utils/atoms"; 9 import { useHydratedEmbed } from "~/utils/useHydrated"; 10 import { 11 useQueryConstellation, ··· 401 // path: ".reply.parent.uri", 402 // }); 403 404 + const [constellationurl] = useAtom(constellationURLAtom) 405 + 406 const infinitequeryresults = useInfiniteQuery({ 407 ...yknowIReallyHateThisButWhateverGuardedConstructConstellationInfiniteQueryLinks( 408 { 409 + constellation: constellationurl, 410 method: "/links", 411 target: atUri, 412 collection: "app.bsky.feed.post",
+9 -1
src/routes/profile.$did/post.$rkey.tsx
··· 1 import { AtUri } from "@atproto/api"; 2 import { useInfiniteQuery, useQueryClient } from "@tanstack/react-query"; 3 import { createFileRoute, Outlet } from "@tanstack/react-router"; 4 import React, { useLayoutEffect } from "react"; 5 6 import { Header } from "~/components/Header"; 7 import { UniversalPostRendererATURILoader } from "~/components/UniversalPostRenderer"; 8 //import { usePersistentStore } from '~/providers/PersistentStoreProvider'; 9 import { 10 constructPostQuery, ··· 275 // path: ".reply.parent.uri", 276 // }); 277 // const replies = repliesData?.linking_records.slice(0, 50) ?? []; 278 const infinitequeryresults = useInfiniteQuery({ 279 ...yknowIReallyHateThisButWhateverGuardedConstructConstellationInfiniteQueryLinks( 280 { 281 method: "/links", 282 target: atUri, 283 collection: "app.bsky.feed.post", ··· 386 } 387 }, [parents, layoutReady]); 388 389 React.useEffect(() => { 390 if (parentsLoading) { 391 setLayoutReady(false); ··· 414 while (currentParentUri && safetyCounter < MAX_PARENTS) { 415 try { 416 const parentPost = await queryClient.fetchQuery( 417 - constructPostQuery(currentParentUri) 418 ); 419 if (!parentPost) break; 420 parentChain.push(parentPost);
··· 1 import { AtUri } from "@atproto/api"; 2 import { useInfiniteQuery, useQueryClient } from "@tanstack/react-query"; 3 import { createFileRoute, Outlet } from "@tanstack/react-router"; 4 + import { useAtom } from "jotai"; 5 import React, { useLayoutEffect } from "react"; 6 7 import { Header } from "~/components/Header"; 8 import { UniversalPostRendererATURILoader } from "~/components/UniversalPostRenderer"; 9 + import { constellationURLAtom, slingshotURLAtom } from "~/utils/atoms"; 10 //import { usePersistentStore } from '~/providers/PersistentStoreProvider'; 11 import { 12 constructPostQuery, ··· 277 // path: ".reply.parent.uri", 278 // }); 279 // const replies = repliesData?.linking_records.slice(0, 50) ?? []; 280 + const [constellationurl] = useAtom(constellationURLAtom) 281 + 282 const infinitequeryresults = useInfiniteQuery({ 283 ...yknowIReallyHateThisButWhateverGuardedConstructConstellationInfiniteQueryLinks( 284 { 285 + constellation: constellationurl, 286 method: "/links", 287 target: atUri, 288 collection: "app.bsky.feed.post", ··· 391 } 392 }, [parents, layoutReady]); 393 394 + 395 + const [slingshoturl] = useAtom(slingshotURLAtom) 396 + 397 React.useEffect(() => { 398 if (parentsLoading) { 399 setLayoutReady(false); ··· 422 while (currentParentUri && safetyCounter < MAX_PARENTS) { 423 try { 424 const parentPost = await queryClient.fetchQuery( 425 + constructPostQuery(currentParentUri, slingshoturl) 426 ); 427 if (!parentPost) break; 428 parentChain.push(parentPost);
+5 -4
src/routes/settings.tsx
··· 30 <Login /> 31 <TextInputSetting 32 atom={constellationURLAtom} 33 - title={"Constellation URL"} 34 description={ 35 - "customize the Constellation instance to be used by Red Dwarf" 36 } 37 init={defaultconstellationURL} 38 /> 39 <TextInputSetting 40 atom={slingshotURLAtom} 41 - title={"Slingshot URL"} 42 - description={"customize the Slingshot instance to be used by Red Dwarf"} 43 init={defaultslingshotURL} 44 /> 45 </> 46 ); 47 }
··· 30 <Login /> 31 <TextInputSetting 32 atom={constellationURLAtom} 33 + title={"Constellation"} 34 description={ 35 + "Customize the Constellation instance to be used by Red Dwarf" 36 } 37 init={defaultconstellationURL} 38 /> 39 <TextInputSetting 40 atom={slingshotURLAtom} 41 + title={"Slingshot"} 42 + description={"Customize the Slingshot instance to be used by Red Dwarf"} 43 init={defaultslingshotURL} 44 /> 45 + <span className="text-gray-500 dark:text-gray-400 py-4 px-6">please restart/refresh the app if changes arent applying correctly</span> 46 </> 47 ); 48 }
+20 -18
src/utils/useQuery.ts
··· 6 useInfiniteQuery, 7 useQuery, 8 type UseQueryResult} from "@tanstack/react-query"; 9 10 - import { constellationURLAtom, slingshotURLAtom, store } from "./atoms"; 11 12 - export function constructIdentityQuery(didorhandle?: string) { 13 return queryOptions({ 14 queryKey: ["identity", didorhandle], 15 queryFn: async () => { 16 if (!didorhandle) return undefined as undefined 17 - const slingshoturl = store.get(slingshotURLAtom) 18 const res = await fetch( 19 `https://${slingshoturl}/xrpc/com.bad-example.identity.resolveMiniDoc?identifier=${encodeURIComponent(didorhandle)}` 20 ); ··· 58 Error 59 > 60 export function useQueryIdentity(didorhandle?: string) { 61 - return useQuery(constructIdentityQuery(didorhandle)); 62 } 63 64 - export function constructPostQuery(uri?: string) { 65 return queryOptions({ 66 queryKey: ["post", uri], 67 queryFn: async () => { 68 if (!uri) return undefined as undefined 69 - const slingshoturl = store.get(slingshotURLAtom) 70 const res = await fetch( 71 `https://${slingshoturl}/xrpc/com.bad-example.repo.getUriRecord?at_uri=${encodeURIComponent(uri)}` 72 ); ··· 122 Error 123 > 124 export function useQueryPost(uri?: string) { 125 - return useQuery(constructPostQuery(uri)); 126 } 127 128 - export function constructProfileQuery(uri?: string) { 129 return queryOptions({ 130 queryKey: ["profile", uri], 131 queryFn: async () => { 132 if (!uri) return undefined as undefined 133 - const slingshoturl = store.get(slingshotURLAtom) 134 const res = await fetch( 135 `https://${slingshoturl}/xrpc/com.bad-example.repo.getUriRecord?at_uri=${encodeURIComponent(uri)}` 136 ); ··· 186 Error 187 > 188 export function useQueryProfile(uri?: string) { 189 - return useQuery(constructProfileQuery(uri)); 190 } 191 192 // export function constructConstellationQuery( ··· 222 // target: string 223 // ): QueryOptions<linksAllResponse, Error>; 224 export function constructConstellationQuery(query?:{ 225 method: 226 | "/links" 227 | "/links/distinct-dids" ··· 254 const path = query?.path 255 const cursor = query.cursor 256 const dids = query?.dids 257 - const constellation = store.get(constellationURLAtom); 258 const res = await fetch( 259 - `https://${constellation}${method}?target=${encodeURIComponent(target)}${collection ? `&collection=${encodeURIComponent(collection)}` : ""}${path ? `&path=${encodeURIComponent(path)}` : ""}${cursor ? `&cursor=${encodeURIComponent(cursor)}` : ""}${dids ? dids.map((did) => `&did=${encodeURIComponent(did)}`).join("") : ""}` 260 ); 261 if (!res.ok) throw new Error("Failed to fetch post"); 262 try { ··· 345 > 346 | undefined { 347 //if (!query) return; 348 return useQuery( 349 - constructConstellationQuery(query) 350 ); 351 } 352 ··· 451 452 453 454 - export function constructArbitraryQuery(uri?: string) { 455 return queryOptions({ 456 queryKey: ["arbitrary", uri], 457 queryFn: async () => { 458 if (!uri) return undefined as undefined 459 - const slingshoturl = store.get(slingshotURLAtom) 460 const res = await fetch( 461 `https://${slingshoturl}/xrpc/com.bad-example.repo.getUriRecord?at_uri=${encodeURIComponent(uri)}` 462 ); ··· 511 Error 512 >; 513 export function useQueryArbitrary(uri?: string) { 514 - return useQuery(constructArbitraryQuery(uri)); 515 } 516 517 export function constructFallbackNothingQuery(){ ··· 626 627 628 export function yknowIReallyHateThisButWhateverGuardedConstructConstellationInfiniteQueryLinks(query?: { 629 method: '/links' 630 target?: string 631 collection: string 632 path: string 633 }) { 634 - const constellationHost = store.get(constellationURLAtom) 635 console.log( 636 'yknowIReallyHateThisButWhateverGuardedConstructConstellationInfiniteQueryLinks', 637 query, ··· 657 const cursor = pageParam 658 659 const res = await fetch( 660 - `https://${constellationHost}${method}?target=${encodeURIComponent(target)}${ 661 collection ? `&collection=${encodeURIComponent(collection)}` : '' 662 }${path ? `&path=${encodeURIComponent(path)}` : ''}${ 663 cursor ? `&cursor=${encodeURIComponent(cursor)}` : ''
··· 6 useInfiniteQuery, 7 useQuery, 8 type UseQueryResult} from "@tanstack/react-query"; 9 + import { useAtom } from "jotai"; 10 11 + import { constellationURLAtom, slingshotURLAtom } from "./atoms"; 12 13 + export function constructIdentityQuery(didorhandle?: string, slingshoturl?: string) { 14 return queryOptions({ 15 queryKey: ["identity", didorhandle], 16 queryFn: async () => { 17 if (!didorhandle) return undefined as undefined 18 const res = await fetch( 19 `https://${slingshoturl}/xrpc/com.bad-example.identity.resolveMiniDoc?identifier=${encodeURIComponent(didorhandle)}` 20 ); ··· 58 Error 59 > 60 export function useQueryIdentity(didorhandle?: string) { 61 + const [slingshoturl] = useAtom(slingshotURLAtom) 62 + return useQuery(constructIdentityQuery(didorhandle, slingshoturl)); 63 } 64 65 + export function constructPostQuery(uri?: string, slingshoturl?: string) { 66 return queryOptions({ 67 queryKey: ["post", uri], 68 queryFn: async () => { 69 if (!uri) return undefined as undefined 70 const res = await fetch( 71 `https://${slingshoturl}/xrpc/com.bad-example.repo.getUriRecord?at_uri=${encodeURIComponent(uri)}` 72 ); ··· 122 Error 123 > 124 export function useQueryPost(uri?: string) { 125 + const [slingshoturl] = useAtom(slingshotURLAtom) 126 + return useQuery(constructPostQuery(uri, slingshoturl)); 127 } 128 129 + export function constructProfileQuery(uri?: string, slingshoturl?: string) { 130 return queryOptions({ 131 queryKey: ["profile", uri], 132 queryFn: async () => { 133 if (!uri) return undefined as undefined 134 const res = await fetch( 135 `https://${slingshoturl}/xrpc/com.bad-example.repo.getUriRecord?at_uri=${encodeURIComponent(uri)}` 136 ); ··· 186 Error 187 > 188 export function useQueryProfile(uri?: string) { 189 + const [slingshoturl] = useAtom(slingshotURLAtom) 190 + return useQuery(constructProfileQuery(uri, slingshoturl)); 191 } 192 193 // export function constructConstellationQuery( ··· 223 // target: string 224 // ): QueryOptions<linksAllResponse, Error>; 225 export function constructConstellationQuery(query?:{ 226 + constellation: string, 227 method: 228 | "/links" 229 | "/links/distinct-dids" ··· 256 const path = query?.path 257 const cursor = query.cursor 258 const dids = query?.dids 259 const res = await fetch( 260 + `https://${query.constellation}${method}?target=${encodeURIComponent(target)}${collection ? `&collection=${encodeURIComponent(collection)}` : ""}${path ? `&path=${encodeURIComponent(path)}` : ""}${cursor ? `&cursor=${encodeURIComponent(cursor)}` : ""}${dids ? dids.map((did) => `&did=${encodeURIComponent(did)}`).join("") : ""}` 261 ); 262 if (!res.ok) throw new Error("Failed to fetch post"); 263 try { ··· 346 > 347 | undefined { 348 //if (!query) return; 349 + const [constellationurl] = useAtom(constellationURLAtom) 350 return useQuery( 351 + constructConstellationQuery(query && {constellation: constellationurl, ...query}) 352 ); 353 } 354 ··· 453 454 455 456 + export function constructArbitraryQuery(uri?: string, slingshoturl?: string) { 457 return queryOptions({ 458 queryKey: ["arbitrary", uri], 459 queryFn: async () => { 460 if (!uri) return undefined as undefined 461 const res = await fetch( 462 `https://${slingshoturl}/xrpc/com.bad-example.repo.getUriRecord?at_uri=${encodeURIComponent(uri)}` 463 ); ··· 512 Error 513 >; 514 export function useQueryArbitrary(uri?: string) { 515 + const [slingshoturl] = useAtom(slingshotURLAtom) 516 + return useQuery(constructArbitraryQuery(uri, slingshoturl)); 517 } 518 519 export function constructFallbackNothingQuery(){ ··· 628 629 630 export function yknowIReallyHateThisButWhateverGuardedConstructConstellationInfiniteQueryLinks(query?: { 631 + constellation: string, 632 method: '/links' 633 target?: string 634 collection: string 635 path: string 636 }) { 637 console.log( 638 'yknowIReallyHateThisButWhateverGuardedConstructConstellationInfiniteQueryLinks', 639 query, ··· 659 const cursor = pageParam 660 661 const res = await fetch( 662 + `https://${query.constellation}${method}?target=${encodeURIComponent(target)}${ 663 collection ? `&collection=${encodeURIComponent(collection)}` : '' 664 }${path ? `&path=${encodeURIComponent(path)}` : ''}${ 665 cursor ? `&cursor=${encodeURIComponent(cursor)}` : ''