diff --git a/app/lish/[did]/[publication]/[rkey]/Blocks/PublishBskyPostBlock.tsx b/app/lish/[did]/[publication]/[rkey]/Blocks/PublishBskyPostBlock.tsx index 44c41a60..3343af46 100644 --- a/app/lish/[did]/[publication]/[rkey]/Blocks/PublishBskyPostBlock.tsx +++ b/app/lish/[did]/[publication]/[rkey]/Blocks/PublishBskyPostBlock.tsx @@ -113,7 +113,7 @@ export const PubBlueskyPostBlock = (props: { {post.replyCount != null && post.replyCount > 0 && ( <> e.stopPropagation()} diff --git a/app/lish/[did]/[publication]/[rkey]/BlueskyQuotesPage.tsx b/app/lish/[did]/[publication]/[rkey]/BlueskyQuotesPage.tsx index 014664e5..1cfe3139 100644 --- a/app/lish/[did]/[publication]/[rkey]/BlueskyQuotesPage.tsx +++ b/app/lish/[did]/[publication]/[rkey]/BlueskyQuotesPage.tsx @@ -87,17 +87,13 @@ function QuotePost(props: { post: PostView; quotesUri: string }) { const parent = { type: "quotes" as const, uri: quotesUri }; return ( -
openPage(parent, { type: "thread", uri: post.uri })} - > - e.stopPropagation()} - /> -
+ e.stopPropagation()} + className="relative py-2 px-2 hover:bg-bg-page rounded cursor-pointer" + /> ); } diff --git a/app/lish/[did]/[publication]/[rkey]/BskyPostContent.tsx b/app/lish/[did]/[publication]/[rkey]/BskyPostContent.tsx index cb1e5d0b..e9512897 100644 --- a/app/lish/[did]/[publication]/[rkey]/BskyPostContent.tsx +++ b/app/lish/[did]/[publication]/[rkey]/BskyPostContent.tsx @@ -8,7 +8,7 @@ import { QuoteTiny } from "components/Icons/QuoteTiny"; import { Separator } from "components/Layout"; import { useLocalizedDate } from "src/hooks/useLocalizedDate"; import { useHasPageLoaded } from "components/InitialPageLoadProvider"; -import { OpenPage } from "./PostPages"; +import { OpenPage, openPage } from "./PostPages"; import { ThreadLink, QuotesLink } from "./PostLinks"; import { BlueskyLinkTiny } from "components/Icons/BlueskyLinkTiny"; import { Avatar } from "components/Avatar"; @@ -25,8 +25,12 @@ export function BskyPostContent(props: { showEmbed?: boolean; showBlueskyLink?: boolean; onEmbedClick?: (e: React.MouseEvent) => void; - quoteCountOnClick?: (e: React.MouseEvent) => void; - replyCountOnClick?: (e: React.MouseEvent) => void; + quoteEnabled?: boolean; + replyEnabled?: boolean; + replyOnClick?: (e: React.MouseEvent) => void; + replyLine?: { + onToggle: (e: React.MouseEvent) => void; + }; }) { const { post, @@ -35,8 +39,10 @@ export function BskyPostContent(props: { showEmbed = true, showBlueskyLink = true, onEmbedClick, - quoteCountOnClick, - replyCountOnClick, + quoteEnabled, + replyEnabled, + replyOnClick, + replyLine, } = props; const record = post.record as AppBskyFeedPost.Record; @@ -44,126 +50,153 @@ export function BskyPostContent(props: { const url = `https://bsky.app/profile/${post.author.handle}/post/${postId}`; return ( - <> - - -
-
-
-
- {post.author.displayName} -
- - @{post.author.handle} -
- } - didOrHandle={post.author.handle} - /> -
-
- {timeAgo(record.createdAt, { compact: true })} -
+
+ {replyLine && ( +
+
+ )} + +
); } function PostCounts(props: { post: PostView; parent?: OpenPage; - quoteCountOnClick?: (e: React.MouseEvent) => void; - replyCountOnClick?: (e: React.MouseEvent) => void; + quoteEnabled?: boolean; + replyEnabled?: boolean; + replyOnClick?: (e: React.MouseEvent) => void; showBlueskyLink: boolean; url: string; }) { + const replyContent = props.post.replyCount != null && + props.post.replyCount > 0 && ( +
+ + {props.post.replyCount} +
+ ); + + const quoteContent = props.post.quoteCount != null && + props.post.quoteCount > 0 && ( +
+ + {props.post.quoteCount} +
+ ); + return (
- {props.post.replyCount != null && props.post.replyCount > 0 && ( - <> - {props.replyCountOnClick ? ( - - - {props.post.replyCount} - - ) : ( -
- - {props.post.replyCount} -
- )} - - )} - {props.post.quoteCount != null && props.post.quoteCount > 0 && ( - <> - {props.quoteCountOnClick ? ( - - - {props.post.quoteCount} - - ) : ( -
- - {props.post.quoteCount} -
- )} - - )} + {replyContent && + (props.replyEnabled ? ( + + {replyContent} + + ) : ( + replyContent + ))} + {quoteContent && + (props.quoteEnabled ? ( + + {quoteContent} + + ) : ( + quoteContent + ))}
); } diff --git a/app/lish/[did]/[publication]/[rkey]/Interactions/Quotes.tsx b/app/lish/[did]/[publication]/[rkey]/Interactions/Quotes.tsx index 05c1d550..980b6149 100644 --- a/app/lish/[did]/[publication]/[rkey]/Interactions/Quotes.tsx +++ b/app/lish/[did]/[publication]/[rkey]/Interactions/Quotes.tsx @@ -136,26 +136,15 @@ export const MentionsDrawerContent = (props: { const parent = { type: "thread" as const, uri: q.uri }; return ( - + ); })}
diff --git a/app/lish/[did]/[publication]/[rkey]/PostLinks.tsx b/app/lish/[did]/[publication]/[rkey]/PostLinks.tsx index 0800cbda..5762dea8 100644 --- a/app/lish/[did]/[publication]/[rkey]/PostLinks.tsx +++ b/app/lish/[did]/[publication]/[rkey]/PostLinks.tsx @@ -55,22 +55,23 @@ export const prefetchQuotes = (uri: string) => { // Link component for opening thread pages with prefetching export function ThreadLink(props: { - threadUri: string; + postUri: string; parent?: OpenPage; children: React.ReactNode; className?: string; onClick?: (e: React.MouseEvent) => void; }) { - const { threadUri, parent, children, className, onClick } = props; + const { postUri, parent, children, className, onClick } = props; const handleClick = (e: React.MouseEvent) => { + e.stopPropagation(); onClick?.(e); if (e.defaultPrevented) return; - openPage(parent, { type: "thread", uri: threadUri }); + openPage(parent, { type: "thread", uri: postUri }); }; const handlePrefetch = () => { - prefetchThread(threadUri); + prefetchThread(postUri); }; return ( @@ -96,6 +97,7 @@ export function QuotesLink(props: { const { postUri, parent, children, className, onClick } = props; const handleClick = (e: React.MouseEvent) => { + e.stopPropagation(); onClick?.(e); if (e.defaultPrevented) return; openPage(parent, { type: "quotes", uri: postUri }); diff --git a/app/lish/[did]/[publication]/[rkey]/PostPages.tsx b/app/lish/[did]/[publication]/[rkey]/PostPages.tsx index c2305d27..63b3637c 100644 --- a/app/lish/[did]/[publication]/[rkey]/PostPages.tsx +++ b/app/lish/[did]/[publication]/[rkey]/PostPages.tsx @@ -297,7 +297,7 @@ export function PostPages({ - fetchThread(threadUri), + } = useSWR(parentUri ? getThreadKey(parentUri) : null, () => + fetchThread(parentUri), ); return ( @@ -60,15 +60,15 @@ export function ThreadPage(props: { Failed to load thread ) : thread ? ( - + ) : null} ); } -function ThreadContent(props: { thread: ThreadType; threadUri: string }) { - const { thread, threadUri } = props; +function ThreadContent(props: { thread: ThreadType; parentUri: string }) { + const { thread, parentUri: parentUri } = props; const mainPostRef = useRef(null); // Scroll the main post into view when the thread loads @@ -114,7 +114,7 @@ function ThreadContent(props: { thread: ThreadType; threadUri: string }) { post={parent} isMainPost={false} showReplyLine={index < parents.length - 1 || true} - threadUri={threadUri} + parentUri={parentUri} /> ))} @@ -125,7 +125,7 @@ function ThreadContent(props: { thread: ThreadType; threadUri: string }) { post={thread} isMainPost={true} showReplyLine={false} - threadUri={threadUri} + parentUri={parentUri} /> @@ -134,7 +134,7 @@ function ThreadContent(props: { thread: ThreadType; threadUri: string }) {
@@ -148,11 +148,11 @@ function ThreadPost(props: { post: ThreadViewPost; isMainPost: boolean; showReplyLine: boolean; - threadUri: string; + parentUri: string; }) { - const { post, isMainPost, showReplyLine, threadUri } = props; + const { post, isMainPost, showReplyLine, parentUri } = props; const postView = post.post; - const parent = { type: "thread" as const, uri: threadUri }; + const parent = { type: "thread" as const, uri: parentUri }; return (
@@ -165,15 +165,8 @@ function ThreadPost(props: { parent={parent} showBlueskyLink={true} showEmbed={true} - quoteCountOnClick={(e) => { - e.stopPropagation(); - e.preventDefault(); - openPage(parent, { type: "quotes", uri: postView.uri }); - }} - replyCountOnClick={(e) => { - e.stopPropagation(); - e.preventDefault(); - }} + quoteEnabled + replyEnabled />
); @@ -181,12 +174,11 @@ function ThreadPost(props: { function Replies(props: { replies: (ThreadViewPost | NotFoundPost | BlockedPost)[]; - threadUri: string; depth: number; parentAuthorDid?: string; - parentUri?: string; + parentUri: string; }) { - const { replies, threadUri, depth, parentAuthorDid, parentUri } = props; + const { replies, depth, parentAuthorDid, parentUri } = props; const collapsedThreads = useThreadState((s) => s.collapsedThreads); const toggleCollapsed = useThreadState((s) => s.toggleCollapsed); @@ -241,13 +233,8 @@ function Replies(props: { { - e.stopPropagation(); - e.preventDefault(); - if (parentUri) toggleCollapsed(parentUri); - console.log("collapse?"); - }} + parentUri={parentUri} + toggleCollapsed={(uri) => toggleCollapsed(uri)} isCollapsed={isCollapsed} depth={props.depth} /> @@ -255,8 +242,8 @@ function Replies(props: { })} {parentUri && depth > 0 && replies.length > 3 && (
@@ -271,59 +258,42 @@ function Replies(props: { const ReplyPost = (props: { post: ThreadViewPost; isLast: boolean; - threadUri: string; - toggleCollapsed: (e: React.MouseEvent) => void; + parentUri: string; + toggleCollapsed: (uri: string) => void; isCollapsed: boolean; depth: number; }) => { - const { post, threadUri } = props; + const { post, parentUri } = props; const postView = post.post; - const parent = { type: "thread" as const, uri: threadUri }; const hasReplies = props.post.replies && props.post.replies.length > 0; - // was in the middle of trying to get the right set of comments to close when this line is clicked - // then i really need to style the parent and grandparent threads, hide some of the content unless its the main post - // the thread line on them is also weird return (
- {props.depth > 0 && ( - - )} - - + onEmbedClick={(e) => e.stopPropagation()} + className="text-sm z-10" + /> {hasReplies && props.depth < 3 && (
{!props.isCollapsed && ( @@ -331,7 +301,6 @@ const ReplyPost = (props: { @@ -342,8 +311,8 @@ const ReplyPost = (props: { {hasReplies && props.depth >= 3 && ( View more replies