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