From fe62398c7f75e949ce1695b08220da41c4e3b65e Mon Sep 17 00:00:00 2001 From: Jared Pereira Date: Mon, 20 Oct 2025 16:58:43 +0000 Subject: [PATCH] implement subpage interaction drawers and buttons --- lexicons/api/lexicons.ts | 4 +++- lexicons/src/comment.ts | 1 + lexicons/pub/leaflet/comment.json | 3 +++ lexicons/pub/leaflet/publication.json | 3 +-- app/lish/[did]/[publication]/[rkey]/PostPages.tsx | 66 +++++++++++++++++++++++++++++++++++++++++++++++++++--------------- app/lish/[did]/[publication]/[rkey]/QuoteHandler.tsx | 1 + lexicons/api/types/pub/leaflet/comment.ts | 1 + app/lish/[did]/[publication]/[rkey]/Interactions/InteractionDrawer.tsx | 35 ++++++++++++++++++++++++++++------- app/lish/[did]/[publication]/[rkey]/Interactions/Interactions.tsx | 11 +++++++---- app/lish/[did]/[publication]/[rkey]/Interactions/Comments/index.tsx | 13 +++++++++++-- 10 file(s) changed, 107 insertion(s)(+), 31 deletion(s)(-) diff --git a/lexicons/api/lexicons.ts b/lexicons/api/lexicons.ts --- a/lexicons/api/lexicons.ts +++ b/lexicons/api/lexicons.ts @@ -1325,6 +1325,9 @@ ref: 'lex:pub.leaflet.richtext.facet', }, }, + onPage: { + type: 'string', + }, attachment: { type: 'union', refs: ['lex:pub.leaflet.comment#linearDocumentQuote'], @@ -1541,7 +1544,6 @@ }, base_path: { type: 'string', - format: 'uri', }, description: { type: 'string', diff --git a/lexicons/src/comment.ts b/lexicons/src/comment.ts --- a/lexicons/src/comment.ts +++ b/lexicons/src/comment.ts @@ -23,6 +23,7 @@ type: "array", items: { type: "ref", ref: PubLeafletRichTextFacet.id }, }, + onPage: { type: "string" }, attachment: { type: "union", refs: ["#linearDocumentQuote"] }, }, }, diff --git a/lexicons/pub/leaflet/comment.json b/lexicons/pub/leaflet/comment.json --- a/lexicons/pub/leaflet/comment.json +++ b/lexicons/pub/leaflet/comment.json @@ -38,6 +38,9 @@ "ref": "pub.leaflet.richtext.facet" } }, + "onPage": { + "type": "string" + }, "attachment": { "type": "union", "refs": [ diff --git a/lexicons/pub/leaflet/publication.json b/lexicons/pub/leaflet/publication.json --- a/lexicons/pub/leaflet/publication.json +++ b/lexicons/pub/leaflet/publication.json @@ -17,8 +17,7 @@ "maxLength": 2000 }, "base_path": { - "type": "string", - "format": "uri" + "type": "string" }, "description": { "type": "string", diff --git a/app/lish/[did]/[publication]/[rkey]/PostPages.tsx b/app/lish/[did]/[publication]/[rkey]/PostPages.tsx --- a/app/lish/[did]/[publication]/[rkey]/PostPages.tsx +++ b/app/lish/[did]/[publication]/[rkey]/PostPages.tsx @@ -1,5 +1,6 @@ "use client"; import { + PubLeafletComment, PubLeafletDocument, PubLeafletPagesLinearDocument, PubLeafletPublication, @@ -119,14 +120,14 @@ preferences: { showComments?: boolean }; }) { let { identity } = useIdentityData(); - let drawerOpen = useDrawerOpen(document_uri); + let drawer = useDrawerOpen(document_uri); useInitializeOpenPages(); let pages = useOpenPages(); if (!document || !document.documents_in_publications[0].publications) return null; let hasPageBackground = !!pubRecord.theme?.showPageBackground; - let fullPageScroll = !hasPageBackground && !drawerOpen && pages.length === 0; + let fullPageScroll = !hasPageBackground && !drawer && pages.length === 0; let record = document.data as PubLeafletDocument.Record; return ( <> @@ -135,7 +136,7 @@ fullPageScroll={fullPageScroll} cardBorderHidden={!hasPageBackground} id={"post-page"} - drawerOpen={!!drawerOpen} + drawerOpen={!!drawer && !drawer.pageId} > !(c.record as PubLeafletComment.Record)?.onPage, + ).length + } />
@@ -183,16 +188,18 @@
- + {drawer && !drawer.pageId && ( + + )} {pages.map((p) => { let page = record.pages.find( @@ -207,7 +214,7 @@ cardBorderHidden={!hasPageBackground} id={`post-page-${p}`} fullPageScroll={false} - drawerOpen={!!drawerOpen} + drawerOpen={!!drawer && drawer.pageId === page.id} pageOptions={ closePage(page?.id!)} @@ -223,7 +230,36 @@ did={did} prerenderedCodeBlocks={prerenderedCodeBlocks} /> + + q.link.includes(page.id!), + ).length + } + commentsCount={ + document.comments_on_documents.filter( + (c) => + (c.record as PubLeafletComment.Record)?.onPage === + page.id, + ).length + } + /> + {drawer && drawer.pageId === page.id && ( + + )} ); })} diff --git a/app/lish/[did]/[publication]/[rkey]/QuoteHandler.tsx b/app/lish/[did]/[publication]/[rkey]/QuoteHandler.tsx --- a/app/lish/[did]/[publication]/[rkey]/QuoteHandler.tsx +++ b/app/lish/[did]/[publication]/[rkey]/QuoteHandler.tsx @@ -212,6 +212,7 @@ setInteractionState(document_uri, { drawer: "comments", drawerOpen: true, + pageId: position.pageId, commentBox: { quote: position }, }), ); diff --git a/lexicons/api/types/pub/leaflet/comment.ts b/lexicons/api/types/pub/leaflet/comment.ts --- a/lexicons/api/types/pub/leaflet/comment.ts +++ b/lexicons/api/types/pub/leaflet/comment.ts @@ -19,6 +19,7 @@ reply?: ReplyRef plaintext: string facets?: PubLeafletRichtextFacet.Main[] + onPage?: string attachment?: $Typed | { $type: string } [k: string]: unknown } diff --git a/app/lish/[did]/[publication]/[rkey]/Interactions/InteractionDrawer.tsx b/app/lish/[did]/[publication]/[rkey]/Interactions/InteractionDrawer.tsx --- a/app/lish/[did]/[publication]/[rkey]/Interactions/InteractionDrawer.tsx +++ b/app/lish/[did]/[publication]/[rkey]/Interactions/InteractionDrawer.tsx @@ -1,34 +1,53 @@ "use client"; import { Media } from "components/Media"; import { Quotes } from "./Quotes"; -import { useInteractionState } from "./Interactions"; +import { InteractionState, useInteractionState } from "./Interactions"; import { Json } from "supabase/database.types"; import { Comment, Comments } from "./Comments"; import { useSearchParams } from "next/navigation"; import { SandwichSpacer } from "components/LeafletLayout"; +import { decodeQuotePosition } from "../quotePosition"; export const InteractionDrawer = (props: { document_uri: string; quotes: { link: string; bsky_posts: { post_view: Json } | null }[]; comments: Comment[]; did: string; + pageId?: string; }) => { let drawer = useDrawerOpen(props.document_uri); if (!drawer) return null; + + // Filter comments and quotes based on pageId + const filteredComments = props.comments.filter( + (c) => (c.record as any)?.onPage === props.pageId, + ); + + const filteredQuotes = props.pageId + ? props.quotes.filter((q) => q.link.includes(props.pageId!)) + : props.quotes.filter((q) => { + const url = new URL(q.link); + const quoteParam = url.pathname.split("/l-quote/")[1]; + if (!quoteParam) return null; + const quotePosition = decodeQuotePosition(quoteParam); + return !quotePosition?.pageId; + }); + return ( <> -
+
- {drawer === "quotes" ? ( - + {drawer.drawer === "quotes" ? ( + ) : ( )}
@@ -40,8 +59,10 @@ export const useDrawerOpen = (uri: string) => { let params = useSearchParams(); let interactionDrawerSearchParam = params.get("interactionDrawer"); - let { drawerOpen: open, drawer } = useInteractionState(uri); + let { drawerOpen: open, drawer, pageId } = useInteractionState(uri); if (open === false || (open === undefined && !interactionDrawerSearchParam)) return null; - return drawer || interactionDrawerSearchParam; + drawer = + drawer || (interactionDrawerSearchParam as InteractionState["drawer"]); + return { drawer, pageId }; }; diff --git a/app/lish/[did]/[publication]/[rkey]/Interactions/Interactions.tsx b/app/lish/[did]/[publication]/[rkey]/Interactions/Interactions.tsx --- a/app/lish/[did]/[publication]/[rkey]/Interactions/Interactions.tsx +++ b/app/lish/[did]/[publication]/[rkey]/Interactions/Interactions.tsx @@ -10,8 +10,9 @@ import { PostPageContext } from "../PostPageContext"; import { scrollIntoView } from "src/utils/scrollIntoView"; -type InteractionState = { +export type InteractionState = { drawerOpen: undefined | boolean; + pageId?: string; drawer: undefined | "comments" | "quotes"; localComments: Comment[]; commentBox: { quote: QuotePosition | null }; @@ -84,9 +85,10 @@ export function openInteractionDrawer( drawer: "comments" | "quotes", document_uri: string, + pageId?: string, ) { flushSync(() => { - setInteractionState(document_uri, { drawerOpen: true, drawer }); + setInteractionState(document_uri, { drawerOpen: true, drawer, pageId }); }); scrollIntoView("interaction-drawer"); } @@ -97,6 +99,7 @@ compact?: boolean; className?: string; showComments?: boolean; + pageId?: string; }) => { const data = useContext(PostPageContext); const document_uri = data?.uri; @@ -113,7 +116,7 @@ className={`flex gap-1 items-center ${!props.compact && "px-1 py-0.5 border border-border-light rounded-lg trasparent-outline selected-outline"}`} onClick={() => { if (!drawerOpen || drawer !== "quotes") - openInteractionDrawer("quotes", document_uri); + openInteractionDrawer("quotes", document_uri, props.pageId); else setInteractionState(document_uri, { drawerOpen: false }); }} > @@ -130,7 +133,7 @@ className={`flex gap-1 items-center ${!props.compact && "px-1 py-0.5 border border-border-light rounded-lg trasparent-outline selected-outline"}`} onClick={() => { if (!drawerOpen || drawer !== "comments") - openInteractionDrawer("comments", document_uri); + openInteractionDrawer("comments", document_uri, props.pageId); else setInteractionState(document_uri, { drawerOpen: false }); }} > diff --git a/app/lish/[did]/[publication]/[rkey]/Interactions/Comments/index.tsx b/app/lish/[did]/[publication]/[rkey]/Interactions/Comments/index.tsx --- a/app/lish/[did]/[publication]/[rkey]/Interactions/Comments/index.tsx +++ b/app/lish/[did]/[publication]/[rkey]/Interactions/Comments/index.tsx @@ -23,11 +23,20 @@ uri: string; bsky_profiles: { record: Json } | null; }; -export function Comments(props: { document_uri: string; comments: Comment[] }) { +export function Comments(props: { + document_uri: string; + comments: Comment[]; + pageId?: string; +}) { let { identity } = useIdentityData(); let { localComments } = useInteractionState(props.document_uri); let comments = useMemo(() => { - return [...localComments, ...props.comments]; + return [ + ...localComments.filter( + (c) => (c.record as any)?.onPage === props.pageId, + ), + ...props.comments, + ]; }, [props.comments, localComments]); let pathname = usePathname(); let redirectRoute = useMemo(() => { -- tangled.sh