Skip to content

Commit c716f60

Browse files
committed
feat: separate ActivityPub + Bluesky buttons on diff page
- "ActivityPub" button (purple, Mastodon icon) — opens instance picker - "Bluesky" button (blue, butterfly icon) — links to bsky.app post - Each only shows if that platform has a post for this diff - Buttons aligned in a row with Share and Download image - Bluesky at:// URI converted to bsky.app URL
1 parent 77a7065 commit c716f60

2 files changed

Lines changed: 35 additions & 9 deletions

File tree

src/routes/diff/[id]/+page.server.ts

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,15 +29,30 @@ export const load: PageServerLoad = async ({ params }) => {
2929
orderBy: (d, { asc }) => [asc(d.id)]
3030
});
3131

32-
// Find the AP post URI for this diff
32+
// Find syndicated posts for this diff
3333
const apPost = await db.query.socialPosts.findFirst({
3434
where: and(eq(socialPosts.diffId, id), eq(socialPosts.platform, 'activitypub'))
3535
});
3636

37+
const bskyPost = await db.query.socialPosts.findFirst({
38+
where: and(eq(socialPosts.diffId, id), eq(socialPosts.platform, 'bluesky'))
39+
});
40+
41+
// Convert Bluesky post URI (at://) to bsky.app URL
42+
let bskyPostUrl: string | null = null;
43+
if (bskyPost?.postUri) {
44+
// URI format: at://did:plc:xxx/app.bsky.feed.post/yyy
45+
const match = bskyPost.postUri.match(/at:\/\/(did:[^/]+)\/app\.bsky\.feed\.post\/(.+)/);
46+
if (match) {
47+
bskyPostUrl = `https://bsky.app/profile/${match[1]}/post/${match[2]}`;
48+
}
49+
}
50+
3751
return {
3852
diff,
3953
prevDiffId: prevDiff?.id ?? null,
4054
nextDiffId: nextDiff?.id ?? null,
41-
apPostUri: apPost?.postUri ?? null
55+
apPostUri: apPost?.postUri ?? null,
56+
bskyPostUrl
4257
};
4358
};

src/routes/diff/[id]/+page.svelte

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
import { browser } from '$app/environment';
33
44
let { data } = $props();
5-
const { diff, prevDiffId, nextDiffId, apPostUri } = data;
5+
const { diff, prevDiffId, nextDiffId, apPostUri, bskyPostUrl } = data;
66
77
let isMobile = $state(false);
88
let shareMenuOpen = $state(false);
@@ -135,14 +135,22 @@
135135
{/if}
136136
<a href="/api/diff/{diff.id}/full.png" download="diff-{diff.id}-full.png" class="btn">Download image</a>
137137
{#if apPostUri}
138-
<button class="btn btn-fedi" onclick={openOnFediverse} title="View or interact with this post on the fediverse">
139-
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 74 79" fill="currentColor" style="margin-right: 0.3rem;">
140-
<path d="M73.7 17.7c-1-6.2-6.3-11-12.7-12.3C54.5 4 37.2 2 37.2 2h-.1C27 2 19.5 4 13 5.4 6.6 6.7 1.3 11.5.3 17.7c-.5 3.3-.9 7.1-.9 11 0 3.2.1 6.2.3 9 .7 9.4 5.3 17.7 13.4 21.4 3.8 1.8 8.1 2.7 12.5 3 4.5.3 8.7-.3 12.5-1.7 0 0 0 0 0 0-.3-1.4-.6-2.9-1-4.3-4 1.2-8.3 1.6-12.6 1.3-4.3-.3-8.5-1.7-8.8-6.5-.1-.5-.1-1-.1-1.5 4 1 8.1 1.6 12.3 1.8 2.6.1 5.1 0 7.6-.2 7.1-.7 13.3-2.9 14.1-5.3.6-1.8.8-3.8.8-5.9 0 0 0-.1 0-.1v-.2c0-6.3 2.4-7.2 2.4-7.2 2.4-1.1 1.3 4.4 1.3 7.2 0 2.4-.3 5.5-1.1 8.5-.5 2-1.4 3.8-2.5 5.4 4.1-1.7 7.5-4.6 9.5-8.5 2.5-5 2.8-10.9 2.8-15.9 0-3.9-.3-7.7-.9-11z"/>
138+
<button class="btn btn-fedi" onclick={openOnFediverse} title="View this post on the fediverse">
139+
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 74 79" fill="currentColor">
140+
<path d="M73.7 17.7c-1-6.2-6.3-11-12.7-12.3C54.5 4 37.2 2 37.2 2h-.1C27 2 19.5 4 13 5.4 6.6 6.7 1.3 11.5.3 17.7c-.5 3.3-.9 7.1-.9 11 0 3.2.1 6.2.3 9 .7 9.4 5.3 17.7 13.4 21.4 3.8 1.8 8.1 2.7 12.5 3 4.5.3 8.7-.3 12.5-1.7 0 0 0 0 0 0-.3-1.4-.6-2.9-1-4.3-4 1.2-8.3 1.6-12.6 1.3-4.3-.3-8.5-1.7-8.8-6.5-.1-.5-.1-1-.1-1.5 4 1 8.1 1.6 12.3 1.8 2.6.1 5.1 0 7.6-.2 7.1-.7 13.3-2.9 14.1-5.3.6-1.8.8-3.8.8-5.9v-.3c0-6.3 2.4-7.2 2.4-7.2 2.4-1.1 1.3 4.4 1.3 7.2 0 2.4-.3 5.5-1.1 8.5-.5 2-1.4 3.8-2.5 5.4 4.1-1.7 7.5-4.6 9.5-8.5 2.5-5 2.8-10.9 2.8-15.9 0-3.9-.3-7.7-.9-11z"/>
141141
<path d="M61.2 27.2v22.7h-9V28c0-4.6-1.9-7-5.8-7-4.3 0-6.4 2.8-6.4 8.3v12h-9V29.3c0-5.5-2.2-8.3-6.4-8.3-3.9 0-5.8 2.3-5.8 7v21.9h-9V27.2c0-4.6 1.2-8.3 3.5-11 2.4-2.7 5.6-4.1 9.5-4.1 4.5 0 7.9 1.7 10.2 5.2l2.2 3.7 2.2-3.7c2.2-3.5 5.7-5.2 10.2-5.2 3.9 0 7.1 1.4 9.5 4.1 2.3 2.7 3.5 6.4 3.5 11z"/>
142142
</svg>
143-
Also on
143+
ActivityPub
144144
</button>
145145
{/if}
146+
{#if bskyPostUrl}
147+
<a href={bskyPostUrl} target="_blank" rel="noopener" class="btn btn-bsky" title="View this post on Bluesky">
148+
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 568 501" fill="currentColor">
149+
<path d="M123.121 33.664C188.241 82.553 258.281 181.68 284 234.873c25.719-53.192 95.759-152.32 160.879-201.21C491.866-1.611 568-28.906 568 57.947c0 17.346-9.945 145.713-15.778 166.555-20.275 72.453-94.155 90.933-159.875 79.748C507.222 323.8 536.444 388.56 473.333 453.32c-119.86 122.992-172.272-30.859-185.702-70.281-2.462-7.227-3.614-10.608-3.631-7.733-.017-2.875-1.169.506-3.631 7.733-13.43 39.422-65.842 193.273-185.702 70.281-63.111-64.76-33.889-129.52 80.986-149.07-65.72 11.185-139.6-7.295-159.875-79.748C10.945 203.659 1 75.291 1 57.946 1-28.906 77.135-1.612 123.121 33.664z"/>
150+
</svg>
151+
Bluesky
152+
</a>
153+
{/if}
146154
</div>
147155
</header>
148156

@@ -208,13 +216,16 @@
208216
.diff-body { line-height: 1.8; word-wrap: break-word; white-space: pre-line; }
209217
.diff-nav { display: flex; justify-content: space-between; padding-top: 1.5rem; border-top: 1px solid var(--color-border); }
210218
.diff-nav a { color: var(--color-primary); text-decoration: none; }
211-
.actions { display: flex; gap: 0.5rem; margin-top: 1rem; align-items: flex-start; flex-wrap: wrap; }
212-
.btn { display: inline-flex; align-items: center; padding: 0.4rem 0.75rem; border-radius: 0.25rem; font-size: 0.85rem; cursor: pointer; text-decoration: none; border: 1px solid var(--color-border); background: white; color: var(--color-text); }
219+
.actions { display: flex; gap: 0.5rem; margin-top: 1rem; align-items: center; flex-wrap: wrap; }
220+
.btn { display: inline-flex; align-items: center; gap: 0.3rem; padding: 0.4rem 0.75rem; border-radius: 0.25rem; font-size: 0.85rem; cursor: pointer; text-decoration: none; border: 1px solid var(--color-border); background: white; color: var(--color-text); }
213221
.btn:hover { border-color: var(--color-primary); color: var(--color-primary); }
214222
.btn-share { background: var(--color-primary); color: white; border-color: var(--color-primary); }
215223
.btn-share:hover { background: #1d4ed8; color: white; }
216224
.btn-fedi { border-color: #6364ff; color: #6364ff; }
217225
.btn-fedi:hover { background: #6364ff; color: white; }
226+
.btn-bsky { border-color: #0085ff; color: #0085ff; }
227+
.btn-bsky:hover { background: #0085ff; color: white; }
228+
.btn-fedi:hover { background: #6364ff; color: white; }
218229
219230
.share-dropdown { position: relative; }
220231
.share-menu {

0 commit comments

Comments
 (0)