+7
-1
lib/components/BlueskyPostList.tsx
+7
-1
lib/components/BlueskyPostList.tsx
···-const { records, loading, error, hasNext, hasPrev, loadNext, loadPrev, pageIndex, pagesCount } = usePaginatedRecords<FeedPostRecord>({ did, collection: 'app.bsky.feed.post', limit });+const { records, loading, error, hasNext, hasPrev, loadNext, loadPrev, pageIndex, pagesCount } = usePaginatedRecords<FeedPostRecord>({
+1
-1
lib/components/LeafletDocument.tsx
+1
-1
lib/components/LeafletDocument.tsx
···+return `at://${encodeURIComponent(did)}/${LEAFLET_DOCUMENT_COLLECTION}/${encodeURIComponent(rkey)}`;
+33
-9
lib/core/AtProtoRecord.tsx
+33
-9
lib/core/AtProtoRecord.tsx
···-export function AtProtoRecord<T = unknown>({ did, collection, rkey, renderer: Renderer, fallback = null, loadingIndicator = 'Loading…' }: AtProtoRecordProps<T>) {+export type AtProtoRecordProps<T = unknown> = AtProtoRecordFetchProps<T> | AtProtoRecordProvidedRecordProps<T>;return <pre style={{ fontSize: 12, padding: 8, background: '#f5f5f5', overflow: 'auto' }}>{JSON.stringify(record, null, 2)}</pre>;
+5
-4
lib/hooks/useAtProtoRecord.ts
+5
-4
lib/hooks/useAtProtoRecord.ts
·········
+161
-38
lib/hooks/usePaginatedRecords.ts
+161
-38
lib/hooks/usePaginatedRecords.ts
······* React hook that fetches a repository collection with cursor-based pagination and prefetching.···* @returns {UsePaginatedRecordsResult<T>} Object containing the current page, pagination metadata, and navigation callbacks.-export function usePaginatedRecords<T>({ did: handleOrDid, collection, limit = 5 }: UsePaginatedRecordsOptions): UsePaginatedRecordsResult<T> {······-const fetchPage = useCallback(async (cursor: string | undefined, targetIndex: number, mode: 'active' | 'prefetch') => {+const fetchPage = useCallback(async (identityKey: string, cursor: string | undefined, targetIndex: number, mode: 'active' | 'prefetch') => {···-) => Promise<{ ok: boolean; data: { records: Array<{ uri: string; rkey?: string; value: T }>; cursor?: string } }>;+const shouldUseAuthorFeed = preferAuthorFeed && collection === 'app.bsky.feed.post' && !feedDisabledRef.current && !!actorIdentifier;+const { rpc } = await createAtprotoClient({ service: authorFeedService ?? DEFAULT_APPVIEW_SERVICE });+) => Promise<{ ok: boolean; data: { feed?: Array<{ post?: { uri?: string; record?: T } }>; cursor?: string } }>;+) => Promise<{ ok: boolean; data: { records: Array<{ uri: string; rkey?: string; value: T }>; cursor?: string } }>;+if (mode === 'active' && token === requestSeq.current && identityKey === identityRef.current) {+if (mode === 'active' && token === requestSeq.current && identityKey === identityRef.current) {······-}, [handleOrDid, did, endpoint, fetchPage, resetState, resolvingDid, resolvingEndpoint, didError, endpointError]);+}, [handleOrDid, identity, fetchPage, resetState, resolvingDid, resolvingEndpoint, didError, endpointError]);···
+2
-1
lib/renderers/BlueskyPostRenderer.tsx
+2
-1
lib/renderers/BlueskyPostRenderer.tsx
+104
-16
lib/utils/atproto-client.ts
+104
-16
lib/utils/atproto-client.ts
···import { CompositeDidDocumentResolver, PlcDidDocumentResolver, WebDidDocumentResolver, XrpcHandleResolver } from '@atcute/identity-resolver';······const plcSource = opts.plcDirectory && opts.plcDirectory.trim() ? opts.plcDirectory : DEFAULT_PLC;const identitySource = opts.identityService && opts.identityService.trim() ? opts.identityService : DEFAULT_IDENTITY_SERVICE;this.didResolver = new CompositeDidDocumentResolver({ methods: { plc: plcResolver, web: webResolver } });+this.handleResolver = new XrpcHandleResolver({ serviceUrl: identityBase, fetch: this.fetchImpl });···+console.warn('[slingshot] resolveHandle payload missing DID; falling back', { handle: normalized });+console.info('[slingshot] resolveHandle cache miss', { handle: normalized, status: response.status });+console.warn('[slingshot] resolveHandle error; falling back to identity service', { handle: normalized, error: slingshotError });+console.warn('[slingshot] resolveHandle fallback failed', { handle: normalized, error: slingshotError });+function createSlingshotAwareHandler(service: string, fetchImpl: typeof fetch): FetchHandler {+const matched = SLINGSHOT_RETRY_PATHS.find(candidate => pathname === candidate || pathname.startsWith(`${candidate}?`));+console.info(`[slingshot] cache miss ${slingshotResponse.status} for ${matched}, falling back to ${service}`);
+1
-1
package.json
+1
-1
package.json
+9
-7
src/App.tsx
+9
-7
src/App.tsx
···const LatestPostSummary: React.FC<{ did: string; handle?: string; colorScheme: ColorSchemePreference }> = ({ did, colorScheme }) => {-const { rkey, loading, error } = useLatestRecord<FeedPostRecord>(did, BLUESKY_POST_COLLECTION);+const { record, rkey, loading, error } = useLatestRecord<FeedPostRecord>(did, BLUESKY_POST_COLLECTION);···