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>(undefined);
19
20export function AtProtoProvider({ children, plcDirectory }: AtProtoProviderProps) {
21 const normalizedPlc = useMemo(() => normalizeBaseUrl(plcDirectory && plcDirectory.trim() ? plcDirectory : 'https://plc.directory'), [plcDirectory]);
22 const resolver = useMemo(() => new ServiceResolver({ plcDirectory: normalizedPlc }), [normalizedPlc]);
23 const cachesRef = useRef<{ didCache: DidCache; blobCache: BlobCache } | null>(null);
24 if (!cachesRef.current) {
25 cachesRef.current = { didCache: new DidCache(), blobCache: new BlobCache() };
26 }
27 const value = useMemo<AtProtoContextValue>(() => ({
28 resolver,
29 plcDirectory: normalizedPlc,
30 didCache: cachesRef.current!.didCache,
31 blobCache: cachesRef.current!.blobCache,
32 }), [resolver, normalizedPlc]);
33 return <AtProtoContext.Provider value={value}>{children}</AtProtoContext.Provider>;
34}
35
36export function useAtProto() {
37 const ctx = useContext(AtProtoContext);
38 if (!ctx) throw new Error('useAtProto must be used within AtProtoProvider');
39 return ctx;
40}