Personal blog finxol.io
blog

Add Bluesky comments to blog posts #1

merged opened by finxol.io targeting main from feat/add-bsky-comments

Add a bsky post cid to have display comments directly in the blog post

Labels

None yet.

Participants 1
AT URI
at://did:plc:hpmpe3pzpdtxbmvhlwrevhju/sh.tangled.repo.pull/3m6ehz6pa3k22
+84 -101
Interdiff #3 โ†’ #4
.zed/settings.json

This file has not been changed.

+24 -68
app/components/BskyComments.vue
··· 29 30 <template> 31 <div class="md:w-[80%] mx-auto mt-16"> 32 - <div class="flex items-baseline gap-4"> 33 <h3 class="font-bold text-xl">Join the conversation!</h3> 34 - <p class="text-gray-500 text-sm" title="Replies"> 35 - <Icon name="ri:reply-line" class="-mb-[2px] mr-1" /> 36 - {{post.post.replyCount}} 37 - </p> 38 - <p class="text-gray-500 text-sm" title="Likes"> 39 - <Icon name="ri:heart-3-line" class="-mb-[2px] mr-1" /> 40 - <span> 41 - {{post.post.likeCount}} 42 - </span> 43 - </p> 44 - <p class="text-gray-500 text-sm" title="Bookmarks"> 45 - <Icon name="ri:bookmark-line" class="-mb-[2px] mr-1" /> 46 - {{post.post.bookmarkCount}} 47 - </p> 48 </div> 49 50 <p class="text-gray-600 text-md mb-6"> ··· 60 <div>No replies yet!</div> 61 </div> 62 63 - <div v-else v-for="reply in post.replies" class="mt-6"> 64 - <BskyPost :post="reply" :depth="0" /> 65 - 66 - <!-- <a :href="`https://bsky.app/profile/${reply.post.author.handle}`" class="flex items-center gap-2 text-blue-500 hover:underline w-fit"> 67 - <img :src="reply.post.author.avatar" :alt="reply.post.author.displayName" class="size-8 rounded-full" /> 68 - <span> 69 - {{ reply.post.author.displayName }} 70 - </span> 71 - </a> 72 - <div class="ml-10">{{ reply.post.record.text }}</div> 73 - <div class="flex items-baseline gap-4 ml-10 mt-2"> 74 - <p class="text-gray-500 text-sm" title="Replies"> 75 - <Icon name="ri:reply-line" class="-mb-[2px] mr-1" /> 76 - {{reply.post.replyCount}} 77 - </p> 78 - <p class="text-gray-500 text-sm" title="Likes"> 79 - <Icon name="ri:heart-3-line" class="-mb-[2px] mr-1" /> 80 - <span> 81 - {{reply.post.likeCount}} 82 - </span> 83 - </p> 84 - <p class="text-gray-500 text-sm" title="Bookmarks"> 85 - <Icon name="ri:bookmark-line" class="-mb-[2px] mr-1" /> 86 - {{reply.post.bookmarkCount}} 87 - </p> 88 - </div> 89 - 90 - <div v-for="rep in reply.replies" class="mt-6 ml-10"> 91 - <a :href="`https://bsky.app/profile/${rep.post.author.handle}`" class="flex items-center gap-2 text-blue-500 hover:underline w-fit"> 92 - <img :src="rep.post.author.avatar" :alt="rep.post.author.displayName" class="size-8 rounded-full" /> 93 - <span> 94 - {{ rep.post.author.displayName }} 95 - </span> 96 - </a> 97 - <div class="ml-10">{{ rep.post.record.text }}</div> 98 - <div class="flex items-baseline gap-4 ml-10 mt-2"> 99 - <p class="text-gray-500 text-sm" title="Replies"> 100 - <Icon name="ri:reply-line" class="-mb-[2px] mr-1" /> 101 - {{rep.post.replyCount}} 102 - </p> 103 - <p class="text-gray-500 text-sm" title="Likes"> 104 - <Icon name="ri:heart-3-line" class="-mb-[2px] mr-1" /> 105 - <span> 106 - {{rep.post.likeCount}} 107 - </span> 108 - </p> 109 - <p class="text-gray-500 text-sm" title="Bookmarks"> 110 - <Icon name="ri:bookmark-line" class="-mb-[2px] mr-1" /> 111 - {{rep.post.bookmarkCount}} 112 - </p> 113 - </div> 114 - </div> --> 115 - </div> 116 </div> 117 </div> 118 </template>
··· 29 30 <template> 31 <div class="md:w-[80%] mx-auto mt-16"> 32 + <div class="flex items-baseline flex-col md:flex-row md:gap-4 mb-2 md:mb-0"> 33 <h3 class="font-bold text-xl">Join the conversation!</h3> 34 + <div class="flex items-center gap-2"> 35 + <p class="text-gray-500 text-sm" title="Replies"> 36 + <Icon name="ri:reply-line" class="-mb-[2px] mr-1" /> 37 + {{post.post.replyCount}} 38 + </p> 39 + <p class="text-gray-500 text-sm" title="Likes"> 40 + <Icon name="ri:heart-3-line" class="-mb-[2px] mr-1" /> 41 + <span> 42 + {{post.post.likeCount}} 43 + </span> 44 + </p> 45 + <p class="text-gray-500 text-sm" title="Bookmarks"> 46 + <Icon name="ri:bookmark-line" class="-mb-[2px] mr-1" /> 47 + {{post.post.bookmarkCount}} 48 + </p> 49 + </div> 50 </div> 51 52 <p class="text-gray-600 text-md mb-6"> ··· 62 <div>No replies yet!</div> 63 </div> 64 65 + <BskyPost 66 + v-else 67 + v-for="reply in post.replies" 68 + :key="reply.post.cid" 69 + :post="reply" 70 + :depth="0" 71 + /> 72 </div> 73 </div> 74 </template>
+59 -32
app/components/BskyPost.vue
··· 8 }>(); 9 const { post, depth } = toRefs(props); 10 11 - const MAX_DEPTH = 2; // Max number of replies to a reply 12 </script> 13 14 <template> 15 - <div v-if="post && depth <= MAX_DEPTH" :class="['mt-6', depth > 0 ? 'ml-10' : '']"> 16 - <a :href="`https://bsky.app/profile/${post.post.author.handle}`" class="flex items-center gap-2 text-blue-500 hover:underline w-fit"> 17 <img :src="post.post.author.avatar" :alt="post.post.author.displayName" class="size-8 rounded-full" /> 18 - <span> 19 - {{ post.post.author.displayName }} 20 - </span> 21 </a> 22 - <div class="ml-10">{{ post.post.record.text }}</div> 23 - <div class="flex items-baseline gap-4 ml-10 mt-2"> 24 - <p class="text-gray-500 text-sm" title="Replies"> 25 - <Icon name="ri:reply-line" class="-mb-[2px] mr-1" /> 26 - {{post.post.replyCount}} 27 - </p> 28 - <p class="text-gray-500 text-sm" title="Likes"> 29 - <Icon name="ri:heart-3-line" class="-mb-[2px] mr-1" /> 30 - <span> 31 - {{post.post.likeCount}} 32 - </span> 33 - </p> 34 - <p class="text-gray-500 text-sm" title="Bookmarks"> 35 - <Icon name="ri:bookmark-line" class="-mb-[2px] mr-1" /> 36 - {{post.post.bookmarkCount}} 37 - </p> 38 - </div> 39 - 40 - <div v-if="post.replies"> 41 - <div v-if="depth === MAX_DEPTH"> 42 - <a :href="`https://bsky.app/profile/${post.post.author.handle}/post/${extractPostId(post.post.uri)}`" class="text-gray-500 text-sm flex items-center gap-2 mt-4 ml-10"> 43 - View more replies on Bluesky 44 - <Icon name='ri:arrow-drop-right-line' /> 45 - </a> 46 </div> 47 - <div v-for="reply in post.replies"> 48 - <BskyPost v-if="reply.$type === 'app.bsky.feed.defs#threadViewPost'" :post="reply" :depth="depth + 1" /> 49 </div> 50 </div> 51 </div> 52 </template>
··· 8 }>(); 9 const { post, depth } = toRefs(props); 10 11 + const MAX_DEPTH = 3; // Max number of replies to a reply 12 + 13 + console.log(post); 14 </script> 15 16 <template> 17 + <div v-if="post && depth < MAX_DEPTH" class="mt-6 bsky-post"> 18 + <a :href="`https://bsky.app/profile/${post.post.author.handle}`"> 19 <img :src="post.post.author.avatar" :alt="post.post.author.displayName" class="size-8 rounded-full" /> 20 </a> 21 + <div class="flex flex-col gap-1"> 22 + <a :href="`https://bsky.app/profile/${post.post.author.handle}`" class="text-md font-bold w-fit"> 23 + {{ post.post.author.displayName }} 24 + </a> 25 + <div> 26 + {{ post.post.record.text }} 27 </div> 28 + <div class="flex items-baseline gap-4 mt-2"> 29 + <p class="text-gray-500 text-sm" title="Replies"> 30 + <Icon name="ri:reply-line" class="-mb-[2px] mr-1" /> 31 + {{post.post.replyCount}} 32 + </p> 33 + <p class="text-gray-500 text-sm" title="Likes"> 34 + <Icon name="ri:heart-3-line" class="-mb-[2px] mr-1" /> 35 + <span> 36 + {{post.post.likeCount}} 37 + </span> 38 + </p> 39 + <p class="text-gray-500 text-sm" title="Bookmarks"> 40 + <Icon name="ri:bookmark-line" class="-mb-[2px] mr-1" /> 41 + {{post.post.bookmarkCount}} 42 + </p> 43 </div> 44 + 45 + <div v-if="post.replies && post.replies.length > 0"> 46 + <div v-if="depth+1 === MAX_DEPTH"> 47 + <a :href="`https://bsky.app/profile/${post.post.author.handle}/post/${extractPostId(post.post.uri)}`" class="text-gray-500 text-sm flex items-center gap-2 mt-4"> 48 + View more replies on Bluesky 49 + <Icon name='ri:arrow-drop-right-line' /> 50 + </a> 51 + </div> 52 + <div v-else v-for="reply in post.replies"> 53 + <BskyPost v-if="reply.$type === 'app.bsky.feed.defs#threadViewPost'" :post="reply" :depth="depth + 1" /> 54 + </div> 55 + </div> 56 </div> 57 </div> 58 </template> 59 + 60 + <style scoped> 61 + .bsky-post { 62 + @apply gap-2 md:gap-4; 63 + 64 + display: grid; 65 + grid-template-columns: auto 1fr; 66 + grid-template-areas: 67 + "avatar content"; 68 + align-items: start; 69 + 70 + & > a:has(> img) { 71 + grid-area: avatar; 72 + } 73 + 74 + & > div { 75 + grid-area: content; 76 + } 77 + 78 + } 79 + </style>
app/components/ShareActions.vue

This file has not been changed.

+1 -1
app/pages/posts/[...slug].vue
··· 95 <BskyComments v-if="post.bskyCid" :cid="post.bskyCid" /> 96 97 <template #fallback> 98 - <h1 class="text-xl font-bold text-stone-600">Loading comments...</h1> 99 </template> 100 </Suspense> 101
··· 95 <BskyComments v-if="post.bskyCid" :cid="post.bskyCid" /> 96 97 <template #fallback> 98 + <h1 class="md:w-[80%] mx-auto mt-16 text-xl font-bold text-stone-600">Loading comments...</h1> 99 </template> 100 </Suspense> 101
app/util/atproto.ts

This file has not been changed.

blog.config.ts

This file has not been changed.

content/posts/blog-template.md

This file has not been changed.

content/posts/embracing-atproto-pt-1-hosting-pds.md

This file has not been changed.

content/posts/embracing-atproto-pt-2-tangled-knot.md

This file has not been changed.

content/posts/extending-openauth.md

This file has not been changed.

content.config.ts

This file has not been changed.

deno.jsonc

This file has not been changed.

globals.ts

This file has not been changed.

package.json

This file has not been changed.

pnpm-lock.yaml

This file has not been changed.

tsconfig.json

This file has not been changed.

History

5 rounds 1 comment
sign up or login to add to the discussion
10 commits
expand
chore: add bsky post cid to content schema
chore: add deps
feat: first draft at bsky replies
fix: add loading state
feat: improve appearance
feat: add icons and bsky stats
feat: add bsky post CIDs to more blog posts
feat: show reply replies, max depth 2
fix: properly align elements
fix: max depth truncate + post elements alignment
expand 0 comments
pull request successfully merged
8 commits
expand
chore: add bsky post cid to content schema
chore: add deps
feat: first draft at bsky replies
fix: add loading state
feat: improve appearance
feat: add icons and bsky stats
feat: add bsky post CIDs to more blog posts
feat: show reply replies, max depth 2
expand 1 comment

Still needs some minor adjustments

3 commits
expand
chore: add bsky post cid to content schema
chore: add deps
feat: first draft at bsky replies
expand 0 comments
1 commit
expand
chore: add bsky post cid to content schema
expand 0 comments
1 commit
expand
chore: add bsky post cid to content schema
expand 0 comments