A React component library for rendering common AT Protocol records for applications such as Bluesky and Leaflet.
1/* eslint-disable react-refresh/only-export-components */ 2import React, { createContext, useContext, useMemo, useRef } from "react"; 3import { ServiceResolver, normalizeBaseUrl } from "../utils/atproto-client"; 4import { BlobCache, DidCache } from "../utils/cache"; 5 6export interface AtProtoProviderProps { 7 children: React.ReactNode; 8 plcDirectory?: string; 9} 10 11interface AtProtoContextValue { 12 resolver: ServiceResolver; 13 plcDirectory: string; 14 didCache: DidCache; 15 blobCache: BlobCache; 16} 17 18const AtProtoContext = createContext<AtProtoContextValue | undefined>( 19 undefined, 20); 21 22export function AtProtoProvider({ 23 children, 24 plcDirectory, 25}: AtProtoProviderProps) { 26 const normalizedPlc = useMemo( 27 () => 28 normalizeBaseUrl( 29 plcDirectory && plcDirectory.trim() 30 ? plcDirectory 31 : "https://plc.directory", 32 ), 33 [plcDirectory], 34 ); 35 const resolver = useMemo( 36 () => new ServiceResolver({ plcDirectory: normalizedPlc }), 37 [normalizedPlc], 38 ); 39 const cachesRef = useRef<{ 40 didCache: DidCache; 41 blobCache: BlobCache; 42 } | null>(null); 43 if (!cachesRef.current) { 44 cachesRef.current = { 45 didCache: new DidCache(), 46 blobCache: new BlobCache(), 47 }; 48 } 49 const value = useMemo<AtProtoContextValue>( 50 () => ({ 51 resolver, 52 plcDirectory: normalizedPlc, 53 didCache: cachesRef.current!.didCache, 54 blobCache: cachesRef.current!.blobCache, 55 }), 56 [resolver, normalizedPlc], 57 ); 58 return ( 59 <AtProtoContext.Provider value={value}> 60 {children} 61 </AtProtoContext.Provider> 62 ); 63} 64 65export function useAtProto() { 66 const ctx = useContext(AtProtoContext); 67 if (!ctx) throw new Error("useAtProto must be used within AtProtoProvider"); 68 return ctx; 69}