a tool for shared writing and social publishing

open sub-page if quoted

+49 -5
+46 -3
app/lish/[did]/[publication]/[rkey]/PostPages.tsx
··· 24 24 import { PageOptionButton } from "components/Pages/PageOptions"; 25 25 import { CloseTiny } from "components/Icons/CloseTiny"; 26 26 import { PageWrapper } from "components/Pages/Page"; 27 - import { Fragment } from "react"; 27 + import { Fragment, useEffect } from "react"; 28 28 import { flushSync } from "react-dom"; 29 29 import { scrollIntoView } from "src/utils/scrollIntoView"; 30 - export const usePostPageUIState = create(() => ({ 30 + import { useParams } from "next/navigation"; 31 + import { decodeQuotePosition } from "./quotePosition"; 32 + 33 + const usePostPageUIState = create(() => ({ 31 34 pages: [] as string[], 35 + initialized: false, 32 36 })); 33 37 38 + export const useOpenPages = () => { 39 + const { quote } = useParams(); 40 + const state = usePostPageUIState((s) => s); 41 + 42 + if (!state.initialized && quote) { 43 + const decodedQuote = decodeQuotePosition(quote as string); 44 + if (decodedQuote?.pageId) { 45 + return [decodedQuote.pageId]; 46 + } 47 + } 48 + 49 + return state.pages; 50 + }; 51 + 52 + export const useInitializeOpenPages = () => { 53 + const { quote } = useParams(); 54 + 55 + useEffect(() => { 56 + const state = usePostPageUIState.getState(); 57 + if (!state.initialized) { 58 + if (quote) { 59 + const decodedQuote = decodeQuotePosition(quote as string); 60 + if (decodedQuote?.pageId) { 61 + usePostPageUIState.setState({ 62 + pages: [decodedQuote.pageId], 63 + initialized: true, 64 + }); 65 + return; 66 + } 67 + } 68 + // Mark as initialized even if no pageId found 69 + usePostPageUIState.setState({ initialized: true }); 70 + } 71 + }, [quote]); 72 + }; 73 + 34 74 export const openPage = (parent: string | undefined, page: string) => { 35 75 flushSync(() => { 36 76 usePostPageUIState.setState((state) => { ··· 40 80 parentPosition === -1 41 81 ? [page] 42 82 : [...state.pages.slice(0, parentPosition + 1), page], 83 + initialized: true, 43 84 }; 44 85 }); 45 86 }); ··· 52 93 let parentPosition = state.pages.findIndex((s) => s == page); 53 94 return { 54 95 pages: state.pages.slice(0, parentPosition), 96 + initialized: true, 55 97 }; 56 98 }); 57 99 ··· 78 120 }) { 79 121 let { identity } = useIdentityData(); 80 122 let drawerOpen = useDrawerOpen(document_uri); 81 - let pages = usePostPageUIState((s) => s.pages); 123 + useInitializeOpenPages(); 124 + let pages = useOpenPages(); 82 125 if (!document || !document.documents_in_publications[0].publications) 83 126 return null; 84 127
+3 -2
app/lish/[did]/[publication]/[rkey]/PublishedPageBlock.tsx
··· 14 14 import { AppBskyFeedDefs } from "@atproto/api"; 15 15 import { TextBlock } from "./TextBlock"; 16 16 import { PostPageContext } from "./PostPageContext"; 17 - import { openPage, usePostPageUIState } from "./PostPages"; 17 + import { openPage, useOpenPages } from "./PostPages"; 18 18 19 19 export function PublishedPageLinkBlock(props: { 20 20 blocks: PubLeafletPagesLinearDocument.Block[]; ··· 27 27 bskyPostData: AppBskyFeedDefs.PostView[]; 28 28 }) { 29 29 //switch to use actually state 30 - let isOpen = usePostPageUIState((s) => s.pages.includes(props.pageId)); 30 + let openPages = useOpenPages(); 31 + let isOpen = openPages.includes(props.pageId); 31 32 return ( 32 33 <div 33 34 className={`w-full cursor-pointer