a tool for shared writing and social publishing
at update/delete-blocks 147 lines 4.9 kB view raw
1"use client"; 2import { getRSVPData } from "actions/getRSVPData"; 3import { SWRConfig } from "swr"; 4import { useReplicache } from "src/replicache"; 5import useSWR from "swr"; 6import { callRPC } from "app/api/rpc/client"; 7import { getPollData } from "actions/pollActions"; 8import type { GetLeafletDataReturnType } from "app/api/rpc/[command]/get_leaflet_data"; 9import { createContext, useContext, useMemo } from "react"; 10import { getPublicationMetadataFromLeafletData } from "src/utils/getPublicationMetadataFromLeafletData"; 11import { getPublicationURL } from "app/lish/createPub/getPublicationURL"; 12import { AtUri } from "@atproto/syntax"; 13import { 14 normalizeDocumentRecord, 15 normalizePublicationRecord, 16 type NormalizedDocument, 17 type NormalizedPublication, 18} from "src/utils/normalizeRecords"; 19 20export const StaticLeafletDataContext = createContext< 21 null | GetLeafletDataReturnType["result"]["data"] 22>(null); 23export function PageSWRDataProvider(props: { 24 leaflet_id: string; 25 leaflet_data: GetLeafletDataReturnType["result"]; 26 rsvp_data: Awaited<ReturnType<typeof getRSVPData>>; 27 poll_data: Awaited<ReturnType<typeof getPollData>>; 28 children: React.ReactNode; 29}) { 30 return ( 31 <SWRConfig 32 value={{ 33 fallback: { 34 rsvp_data: props.rsvp_data, 35 poll_data: props.poll_data, 36 [`${props.leaflet_id}-leaflet_data`]: props.leaflet_data.data, 37 }, 38 }} 39 > 40 {props.children} 41 </SWRConfig> 42 ); 43} 44 45export function useRSVPData() { 46 let { permission_token } = useReplicache(); 47 return useSWR(`rsvp_data`, () => 48 getRSVPData( 49 permission_token.permission_token_rights.map((pr) => pr.entity_set), 50 ), 51 ); 52} 53export function usePollData() { 54 let { permission_token } = useReplicache(); 55 return useSWR(`poll_data`, () => 56 getPollData( 57 permission_token.permission_token_rights.map((pr) => pr.entity_set), 58 ), 59 ); 60} 61 62let useLeafletData = () => { 63 let { permission_token } = useReplicache(); 64 let staticLeafletData = useContext(StaticLeafletDataContext); 65 let res = useSWR( 66 staticLeafletData ? null : `${permission_token.id}-leaflet_data`, 67 async () => 68 permission_token.id 69 ? (await callRPC("get_leaflet_data", { token_id: permission_token.id })) 70 ?.result.data 71 : undefined, 72 ); 73 if (staticLeafletData) return { data: staticLeafletData, mutate: res.mutate }; 74 return res; 75}; 76export function useLeafletPublicationData() { 77 let { data, mutate } = useLeafletData(); 78 79 // First check for leaflets in publications 80 let pubData = getPublicationMetadataFromLeafletData(data); 81 82 // Normalize records so consumers don't have to 83 const normalizedPublication = useMemo( 84 () => normalizePublicationRecord(pubData?.publications?.record), 85 [pubData?.publications?.record] 86 ); 87 const normalizedDocument = useMemo( 88 () => normalizeDocumentRecord(pubData?.documents?.data), 89 [pubData?.documents?.data] 90 ); 91 92 return { 93 data: pubData || null, 94 // Pre-normalized data - consumers should use these instead of normalizing themselves 95 normalizedPublication, 96 normalizedDocument, 97 mutate, 98 }; 99} 100export function useLeafletDomains() { 101 let { data, mutate } = useLeafletData(); 102 return { data: data?.custom_domain_routes, mutate: mutate }; 103} 104 105export function useLeafletPublicationStatus() { 106 const data = useContext(StaticLeafletDataContext); 107 if (!data) return null; 108 109 const publishedInPublication = data.leaflets_in_publications?.find( 110 (l) => l.doc, 111 ); 112 const publishedStandalone = data.leaflets_to_documents?.find( 113 (l) => !!l.documents, 114 ); 115 116 const documentUri = 117 publishedInPublication?.documents?.uri ?? publishedStandalone?.document; 118 119 // Compute the full post URL for sharing 120 let postShareLink: string | undefined; 121 if (publishedInPublication?.publications && publishedInPublication.documents) { 122 // Published in a publication - use publication URL + document rkey 123 const docUri = new AtUri(publishedInPublication.documents.uri); 124 postShareLink = `${getPublicationURL(publishedInPublication.publications)}/${docUri.rkey}`; 125 } else if (publishedStandalone?.document) { 126 // Standalone published post - use /p/{did}/{rkey} format 127 const docUri = new AtUri(publishedStandalone.document); 128 postShareLink = `/p/${docUri.host}/${docUri.rkey}`; 129 } 130 131 return { 132 token: data, 133 leafletId: data.root_entity, 134 shareLink: data.id, 135 // Draft state - in a publication but not yet published 136 draftInPublication: 137 data.leaflets_in_publications?.[0]?.publication ?? undefined, 138 // Published state 139 isPublished: !!(publishedInPublication || publishedStandalone), 140 publishedAt: 141 publishedInPublication?.documents?.indexed_at ?? 142 publishedStandalone?.documents?.indexed_at, 143 documentUri, 144 // Full URL for sharing published posts 145 postShareLink, 146 }; 147}