feat: use replyTargets config for platform-to-syndicator mapping

- Frontend now reads replyTargets from isOwner API to resolve which
  syndicator handles replies for each platform
- Build-time reply buttons get platform from URL heuristics as fallback
- enrichBuildTimeBadges upgrades to NodeInfo-resolved platform at runtime
This commit is contained in:
Ricardo
2026-03-26 08:21:54 +01:00
parent dcd73b1897
commit 34fdab4b85
3 changed files with 18 additions and 6 deletions

View File

@@ -153,9 +153,19 @@
<div class="text-surface-700 dark:text-surface-300 prose dark:prose-invert prose-sm max-w-none"> <div class="text-surface-700 dark:text-surface-300 prose dark:prose-invert prose-sm max-w-none">
{{ reply.content.html | safe if reply.content.html else reply.content.text }} {{ reply.content.html | safe if reply.content.html else reply.content.text }}
</div> </div>
{% set replySource = reply['wm-source'] | default('', true) %}
{% set replyAuthorUrl = reply.author.url | default('', true) %}
{% set buildPlatform = 'webmention' %}
{% if 'bsky.app' in replyAuthorUrl or ('brid.gy/' in replySource and '/bluesky/' in replySource) %}
{% set buildPlatform = 'bluesky' %}
{% elif 'brid.gy/' in replySource and '/mastodon/' in replySource %}
{% set buildPlatform = 'mastodon' %}
{% elif 'fed.brid.gy' in replySource %}
{% set buildPlatform = 'activitypub' %}
{% endif %}
<button class="wm-reply-btn hidden text-xs text-primary-600 dark:text-primary-400 hover:underline mt-2" <button class="wm-reply-btn hidden text-xs text-primary-600 dark:text-primary-400 hover:underline mt-2"
data-reply-url="{{ reply.url }}" data-reply-url="{{ reply.url }}"
data-platform=""> data-platform="{{ buildPlatform }}">
Reply Reply
</button> </button>
</div> </div>

View File

@@ -12,6 +12,7 @@ document.addEventListener("alpine:init", () => {
isOwner: false, isOwner: false,
profile: null, profile: null,
syndicationTargets: {}, syndicationTargets: {},
replyTargets: {},
}); });
Alpine.data("commentsSection", (targetUrl) => ({ Alpine.data("commentsSection", (targetUrl) => ({
@@ -74,11 +75,13 @@ document.addEventListener("alpine:init", () => {
photo: data.photo, photo: data.photo,
}; };
this.syndicationTargets = data.syndicationTargets || {}; this.syndicationTargets = data.syndicationTargets || {};
this.replyTargets = data.replyTargets || {};
// Also update global store for webmentions component // Also update global store for webmentions component
Alpine.store("owner").isOwner = true; Alpine.store("owner").isOwner = true;
Alpine.store("owner").profile = this.ownerProfile; Alpine.store("owner").profile = this.ownerProfile;
Alpine.store("owner").syndicationTargets = this.syndicationTargets; Alpine.store("owner").syndicationTargets = this.syndicationTargets;
Alpine.store("owner").replyTargets = this.replyTargets;
// Note: owner:detected event is dispatched from init() after // Note: owner:detected event is dispatched from init() after
// this completes, so the Alpine store is populated before the event fires // this completes, so the Alpine store is populated before the event fires

View File

@@ -803,12 +803,11 @@
btn.addEventListener('click', function() { btn.addEventListener('click', function() {
var replyUrl = btn.dataset.replyUrl; var replyUrl = btn.dataset.replyUrl;
var platform = btn.dataset.platform || 'webmention'; var platform = btn.dataset.platform || 'webmention';
// Map detected platform to syndicator by service.name // Map platform to syndicator via replyTargets config
var targets = ownerStore.syndicationTargets || {}; var targets = ownerStore.syndicationTargets || {};
var syndicateTo = null; var replyTargets = ownerStore.replyTargets || {};
if (platform === 'bluesky') syndicateTo = targets['Bluesky'] || null; var serviceName = replyTargets[platform] || null;
if (platform === 'mastodon') syndicateTo = targets['Mastodon'] || null; var syndicateTo = serviceName ? (targets[serviceName] || null) : null;
if (platform === 'activitypub') syndicateTo = targets['ActivityPub (Fediverse)'] || null;
// Close any existing reply form // Close any existing reply form
closeActiveReplyForm(); closeActiveReplyForm();