Fix follower links, HTMX follow/unfollow, update shared submodule
All checks were successful
Build and Deploy / build-and-deploy (push) Successful in 41s

- Follower profile links now go to https://domain/@username (web profile)
  instead of the AP actor URL which 404s
- Follow Back/Unfollow buttons update via HTMX without full page refresh
- Update shared submodule to decoupling branch with new protocol methods

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
giles
2026-02-22 14:52:11 +00:00
parent 0df06f6d32
commit 45377648c1
3 changed files with 48 additions and 23 deletions

View File

@@ -157,6 +157,8 @@ def register(url_prefix="/social"):
await services.federation.send_follow(
g.s, actor.preferred_username, remote_actor_url,
)
if request.headers.get("HX-Request"):
return await _actor_card_response(actor, remote_actor_url, is_followed=True)
return redirect(request.referrer or url_for("social.search"))
@bp.post("/unfollow")
@@ -168,8 +170,34 @@ def register(url_prefix="/social"):
await services.federation.unfollow(
g.s, actor.preferred_username, remote_actor_url,
)
if request.headers.get("HX-Request"):
return await _actor_card_response(actor, remote_actor_url, is_followed=False)
return redirect(request.referrer or url_for("social.search"))
async def _actor_card_response(actor, remote_actor_url, is_followed):
"""Re-render a single actor card after follow/unfollow via HTMX."""
remote_dto = await services.federation.get_or_fetch_remote_actor(
g.s, remote_actor_url,
)
if not remote_dto:
return Response("", status=200)
followed_urls = {remote_actor_url} if is_followed else set()
# Detect list context from referer
referer = request.referrer or ""
if "/followers" in referer:
list_type = "followers"
else:
list_type = "following"
return await render_template(
"federation/_actor_list_items.html",
actors=[remote_dto],
total=0,
page=1,
list_type=list_type,
followed_urls=followed_urls,
actor=actor,
)
# -- Interactions ---------------------------------------------------------
@bp.post("/like")

2
shared

Submodule shared updated: bccfff0c69...04f7c5e85c

View File

@@ -1,5 +1,6 @@
{% for a in actors %}
<article class="bg-white rounded-lg shadow-sm border border-stone-200 p-4 mb-3 flex items-center gap-4">
<article class="bg-white rounded-lg shadow-sm border border-stone-200 p-4 mb-3 flex items-center gap-4"
id="actor-{{ a.actor_url | replace('/', '_') | replace(':', '_') }}">
{% if a.icon_url %}
<img src="{{ a.icon_url }}" alt="" class="w-12 h-12 rounded-full">
{% else %}
@@ -14,7 +15,7 @@
{{ a.display_name or a.preferred_username }}
</a>
{% else %}
<a href="{{ a.actor_url }}" target="_blank" rel="noopener" class="font-semibold text-stone-900 hover:underline">
<a href="https://{{ a.domain }}/@{{ a.preferred_username }}" target="_blank" rel="noopener" class="font-semibold text-stone-900 hover:underline">
{{ a.display_name or a.preferred_username }}
</a>
{% endif %}
@@ -26,17 +27,11 @@
{% if actor %}
<div class="flex-shrink-0">
{% if list_type == "following" %}
<form method="post" action="{{ url_for('social.unfollow') }}">
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}">
<input type="hidden" name="actor_url" value="{{ a.actor_url }}">
<button type="submit" class="text-sm border border-stone-300 rounded px-3 py-1 hover:bg-stone-100">
Unfollow
</button>
</form>
{% elif list_type == "followers" %}
{% if a.actor_url in followed_urls %}
<form method="post" action="{{ url_for('social.unfollow') }}">
{% if list_type == "following" or a.actor_url in (followed_urls or set()) %}
<form method="post" action="{{ url_for('social.unfollow') }}"
hx-post="{{ url_for('social.unfollow') }}"
hx-target="closest article"
hx-swap="outerHTML">
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}">
<input type="hidden" name="actor_url" value="{{ a.actor_url }}">
<button type="submit" class="text-sm border border-stone-300 rounded px-3 py-1 hover:bg-stone-100">
@@ -44,7 +39,10 @@
</button>
</form>
{% else %}
<form method="post" action="{{ url_for('social.follow') }}">
<form method="post" action="{{ url_for('social.follow') }}"
hx-post="{{ url_for('social.follow') }}"
hx-target="closest article"
hx-swap="outerHTML">
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}">
<input type="hidden" name="actor_url" value="{{ a.actor_url }}">
<button type="submit" class="text-sm bg-stone-800 text-white rounded px-3 py-1 hover:bg-stone-700">
@@ -52,7 +50,6 @@
</button>
</form>
{% endif %}
{% endif %}
</div>
{% endif %}
</article>