a tool for shared writing and social publishing

extract out page component to lineardocumentpage

+179 -108
+1
actions/publishToPublication.ts
··· 228 228 if (b.type === "card") { 229 229 let [page] = scan.eav(b.value, "block/card"); 230 230 if (!page) return; 231 + let [pageType] = scan.eav(page.data.value, "page/type"); 231 232 let blocks = getBlocksWithTypeLocal(facts, page.data.value); 232 233 pages.push({ 233 234 id: page.data.value,
+152
app/lish/[did]/[publication]/[rkey]/LinearDocumentPage.tsx
··· 1 + "use client"; 2 + import { 3 + PubLeafletComment, 4 + PubLeafletDocument, 5 + PubLeafletPagesLinearDocument, 6 + PubLeafletPublication, 7 + } from "lexicons/api"; 8 + import { PostPageData } from "./getPostPageData"; 9 + import { ProfileViewDetailed } from "@atproto/api/dist/client/types/app/bsky/actor/defs"; 10 + import { getPublicationURL } from "app/lish/createPub/getPublicationURL"; 11 + import { SubscribeWithBluesky } from "app/lish/Subscribe"; 12 + import { EditTiny } from "components/Icons/EditTiny"; 13 + import { Interactions } from "./Interactions/Interactions"; 14 + import { PostContent } from "./PostContent"; 15 + import { PostHeader } from "./PostHeader/PostHeader"; 16 + import { useIdentityData } from "components/IdentityProvider"; 17 + import { AppBskyFeedDefs } from "@atproto/api"; 18 + import { useDrawerOpen } from "./Interactions/InteractionDrawer"; 19 + import { PageWrapper } from "components/Pages/Page"; 20 + import { decodeQuotePosition } from "./quotePosition"; 21 + 22 + export function LinearDocumentPage({ 23 + document, 24 + blocks, 25 + did, 26 + profile, 27 + preferences, 28 + pubRecord, 29 + prerenderedCodeBlocks, 30 + bskyPostData, 31 + document_uri, 32 + pageId, 33 + pageOptions, 34 + fullPageScroll, 35 + }: { 36 + document_uri: string; 37 + document: PostPageData; 38 + blocks: PubLeafletPagesLinearDocument.Block[]; 39 + profile?: ProfileViewDetailed; 40 + pubRecord: PubLeafletPublication.Record; 41 + did: string; 42 + prerenderedCodeBlocks?: Map<string, string>; 43 + bskyPostData: AppBskyFeedDefs.PostView[]; 44 + preferences: { showComments?: boolean }; 45 + pageId?: string; 46 + pageOptions?: React.ReactNode; 47 + fullPageScroll: boolean; 48 + }) { 49 + let { identity } = useIdentityData(); 50 + let drawer = useDrawerOpen(document_uri); 51 + 52 + if (!document || !document.documents_in_publications[0].publications) 53 + return null; 54 + 55 + let hasPageBackground = !!pubRecord.theme?.showPageBackground; 56 + let record = document.data as PubLeafletDocument.Record; 57 + 58 + const isSubpage = !!pageId; 59 + 60 + return ( 61 + <> 62 + <PageWrapper 63 + pageType="doc" 64 + fullPageScroll={fullPageScroll} 65 + cardBorderHidden={!hasPageBackground} 66 + id={pageId ? `post-page-${pageId}` : "post-page"} 67 + drawerOpen={ 68 + !!drawer && (pageId ? drawer.pageId === pageId : !drawer.pageId) 69 + } 70 + pageOptions={pageOptions} 71 + > 72 + {!isSubpage && profile && ( 73 + <PostHeader 74 + data={document} 75 + profile={profile} 76 + preferences={preferences} 77 + /> 78 + )} 79 + <PostContent 80 + pages={record.pages as PubLeafletPagesLinearDocument.Main[]} 81 + pageId={pageId} 82 + bskyPostData={bskyPostData} 83 + blocks={blocks} 84 + did={did} 85 + prerenderedCodeBlocks={prerenderedCodeBlocks} 86 + /> 87 + <Interactions 88 + pageId={pageId} 89 + showComments={preferences.showComments} 90 + quotesCount={ 91 + pageId 92 + ? document.document_mentions_in_bsky.filter((q) => 93 + q.link.includes(pageId), 94 + ).length 95 + : document.document_mentions_in_bsky.filter((q) => { 96 + const url = new URL(q.link); 97 + const quoteParam = url.pathname.split("/l-quote/")[1]; 98 + if (!quoteParam) return null; 99 + const quotePosition = decodeQuotePosition(quoteParam); 100 + return !quotePosition?.pageId; 101 + }).length 102 + } 103 + commentsCount={ 104 + pageId 105 + ? document.comments_on_documents.filter( 106 + (c) => 107 + (c.record as PubLeafletComment.Record)?.onPage === pageId, 108 + ).length 109 + : document.comments_on_documents.filter( 110 + (c) => !(c.record as PubLeafletComment.Record)?.onPage, 111 + ).length 112 + } 113 + /> 114 + {!isSubpage && ( 115 + <> 116 + <hr className="border-border-light mb-4 mt-4 sm:mx-4 mx-3" /> 117 + <div className="pb-6 sm:px-4 px-3"> 118 + {identity && 119 + identity.atp_did === 120 + document.documents_in_publications[0]?.publications 121 + ?.identity_did ? ( 122 + <a 123 + href={`https://leaflet.pub/${document.leaflets_in_publications[0]?.leaflet}`} 124 + className="flex gap-2 items-center hover:!no-underline selected-outline px-2 py-0.5 bg-accent-1 text-accent-2 font-bold w-fit rounded-lg !border-accent-1 !outline-accent-1 mx-auto" 125 + > 126 + <EditTiny /> Edit Post 127 + </a> 128 + ) : ( 129 + <SubscribeWithBluesky 130 + isPost 131 + base_url={getPublicationURL( 132 + document.documents_in_publications[0].publications, 133 + )} 134 + pub_uri={ 135 + document.documents_in_publications[0].publications.uri 136 + } 137 + subscribers={ 138 + document.documents_in_publications[0].publications 139 + .publication_subscriptions 140 + } 141 + pubName={ 142 + document.documents_in_publications[0].publications.name 143 + } 144 + /> 145 + )} 146 + </div> 147 + </> 148 + )} 149 + </PageWrapper> 150 + </> 151 + ); 152 + }
+1 -1
app/lish/[did]/[publication]/[rkey]/PostContent.tsx
··· 73 73 ); 74 74 } 75 75 76 - let Block = ({ 76 + export let Block = ({ 77 77 block, 78 78 did, 79 79 isList,
+25 -106
app/lish/[did]/[publication]/[rkey]/PostPages.tsx
··· 1 1 "use client"; 2 2 import { 3 - PubLeafletComment, 4 3 PubLeafletDocument, 5 4 PubLeafletPagesLinearDocument, 6 5 PubLeafletPublication, 7 6 } from "lexicons/api"; 8 7 import { PostPageData } from "./getPostPageData"; 9 8 import { ProfileViewDetailed } from "@atproto/api/dist/client/types/app/bsky/actor/defs"; 10 - import { getPublicationURL } from "app/lish/createPub/getPublicationURL"; 11 - import { SubscribeWithBluesky } from "app/lish/Subscribe"; 12 - import { EditTiny } from "components/Icons/EditTiny"; 13 - import { Interactions } from "./Interactions/Interactions"; 14 - import { PostContent } from "./PostContent"; 15 - import { PostHeader } from "./PostHeader/PostHeader"; 16 - import { useIdentityData } from "components/IdentityProvider"; 17 9 import { AppBskyFeedDefs } from "@atproto/api"; 18 10 import { create } from "zustand/react"; 19 11 import { ··· 23 15 import { BookendSpacer, SandwichSpacer } from "components/LeafletLayout"; 24 16 import { PageOptionButton } from "components/Pages/PageOptions"; 25 17 import { CloseTiny } from "components/Icons/CloseTiny"; 26 - import { PageWrapper } from "components/Pages/Page"; 27 18 import { Fragment, useEffect } from "react"; 28 19 import { flushSync } from "react-dom"; 29 20 import { scrollIntoView } from "src/utils/scrollIntoView"; 30 21 import { useParams } from "next/navigation"; 31 22 import { decodeQuotePosition } from "./quotePosition"; 23 + import { LinearDocumentPage } from "./LinearDocumentPage"; 32 24 33 25 const usePostPageUIState = create(() => ({ 34 26 pages: [] as string[], ··· 124 116 bskyPostData: AppBskyFeedDefs.PostView[]; 125 117 preferences: { showComments?: boolean }; 126 118 }) { 127 - let { identity } = useIdentityData(); 128 119 let drawer = useDrawerOpen(document_uri); 129 120 useInitializeOpenPages(); 130 121 let pages = useOpenPages(); ··· 132 123 return null; 133 124 134 125 let hasPageBackground = !!pubRecord.theme?.showPageBackground; 126 + let record = document.data as PubLeafletDocument.Record; 127 + 135 128 let fullPageScroll = !hasPageBackground && !drawer && pages.length === 0; 136 - let record = document.data as PubLeafletDocument.Record; 137 129 return ( 138 130 <> 139 131 {!fullPageScroll && <BookendSpacer />} 140 - <PageWrapper 141 - pageType="doc" 132 + <LinearDocumentPage 133 + document={document} 134 + blocks={blocks} 135 + did={did} 136 + profile={profile} 142 137 fullPageScroll={fullPageScroll} 143 - cardBorderHidden={!hasPageBackground} 144 - id={"post-page"} 145 - drawerOpen={!!drawer && !drawer.pageId} 146 - > 147 - <PostHeader 148 - data={document} 149 - profile={profile} 150 - preferences={preferences} 151 - /> 152 - <PostContent 153 - pages={record.pages as PubLeafletPagesLinearDocument.Main[]} 154 - bskyPostData={bskyPostData} 155 - blocks={blocks} 156 - did={did} 157 - prerenderedCodeBlocks={prerenderedCodeBlocks} 158 - /> 159 - <Interactions 160 - showComments={preferences.showComments} 161 - quotesCount={ 162 - document.document_mentions_in_bsky.filter((q) => { 163 - const url = new URL(q.link); 164 - const quoteParam = url.pathname.split("/l-quote/")[1]; 165 - if (!quoteParam) return null; 166 - const quotePosition = decodeQuotePosition(quoteParam); 167 - return !quotePosition?.pageId; 168 - }).length 169 - } 170 - commentsCount={ 171 - document.comments_on_documents.filter( 172 - (c) => !(c.record as PubLeafletComment.Record)?.onPage, 173 - ).length 174 - } 175 - /> 176 - <hr className="border-border-light mb-4 mt-4 sm:mx-4 mx-3" /> 177 - <div className="pb-6 sm:px-4 px-3"> 178 - {identity && 179 - identity.atp_did === 180 - document.documents_in_publications[0]?.publications 181 - ?.identity_did ? ( 182 - <a 183 - href={`https://leaflet.pub/${document.leaflets_in_publications[0]?.leaflet}`} 184 - className="flex gap-2 items-center hover:!no-underline selected-outline px-2 py-0.5 bg-accent-1 text-accent-2 font-bold w-fit rounded-lg !border-accent-1 !outline-accent-1 mx-auto" 185 - > 186 - <EditTiny /> Edit Post 187 - </a> 188 - ) : ( 189 - <SubscribeWithBluesky 190 - isPost 191 - base_url={getPublicationURL( 192 - document.documents_in_publications[0].publications, 193 - )} 194 - pub_uri={document.documents_in_publications[0].publications.uri} 195 - subscribers={ 196 - document.documents_in_publications[0].publications 197 - .publication_subscriptions 198 - } 199 - pubName={document.documents_in_publications[0].publications.name} 200 - /> 201 - )} 202 - </div> 203 - </PageWrapper> 138 + preferences={preferences} 139 + pubRecord={pubRecord} 140 + prerenderedCodeBlocks={prerenderedCodeBlocks} 141 + bskyPostData={bskyPostData} 142 + document_uri={document_uri} 143 + /> 204 144 205 145 {drawer && !drawer.pageId && ( 206 146 <InteractionDrawer ··· 223 163 return ( 224 164 <Fragment key={p}> 225 165 <SandwichSpacer /> 226 - {/*JARED TODO : drawerOpen here is checking whether the drawer is open on the first page, rather than if it's open on this page. Please rewire this when you add drawers per page!*/} 227 - <PageWrapper 228 - pageType="doc" 229 - cardBorderHidden={!hasPageBackground} 230 - id={`post-page-${p}`} 166 + <LinearDocumentPage 231 167 fullPageScroll={false} 232 - drawerOpen={!!drawer && drawer.pageId === page.id} 168 + document={document} 169 + blocks={page.blocks} 170 + did={did} 171 + preferences={preferences} 172 + pubRecord={pubRecord} 173 + prerenderedCodeBlocks={prerenderedCodeBlocks} 174 + bskyPostData={bskyPostData} 175 + document_uri={document_uri} 176 + pageId={page.id} 233 177 pageOptions={ 234 178 <PageOptions 235 179 onClick={() => closePage(page?.id!)} 236 180 hasPageBackground={hasPageBackground} 237 181 /> 238 182 } 239 - > 240 - <PostContent 241 - pages={record.pages as PubLeafletPagesLinearDocument.Main[]} 242 - pageId={page.id} 243 - bskyPostData={bskyPostData} 244 - blocks={page.blocks} 245 - did={did} 246 - prerenderedCodeBlocks={prerenderedCodeBlocks} 247 - /> 248 - <Interactions 249 - pageId={page.id} 250 - showComments={preferences.showComments} 251 - quotesCount={ 252 - document.document_mentions_in_bsky.filter((q) => 253 - q.link.includes(page.id!), 254 - ).length 255 - } 256 - commentsCount={ 257 - document.comments_on_documents.filter( 258 - (c) => 259 - (c.record as PubLeafletComment.Record)?.onPage === 260 - page.id, 261 - ).length 262 - } 263 - /> 264 - </PageWrapper> 183 + /> 265 184 {drawer && drawer.pageId === page.id && ( 266 185 <InteractionDrawer 267 186 pageId={page.id}
-1
components/Blocks/BlockCommands.tsx
··· 369 369 name: "New Canvas", 370 370 icon: <BlockCanvasPageSmall />, 371 371 type: "page", 372 - hiddenInPublication: true, 373 372 onSelect: async (rep, props, um) => { 374 373 props.entityID && clearCommandSearchText(props.entityID); 375 374 let entity = await createBlockWithType(rep, props, "card");