From bc6c767c29e7016b24cdc52899ef24d65afe7b27 Mon Sep 17 00:00:00 2001 From: Gabriel Kaszewski Date: Wed, 13 May 2026 01:35:54 +0200 Subject: [PATCH] feat: follow-by-handle form on following and users pages --- .../template-askama/templates/following.html | 6 ++++++ crates/adapters/template-askama/templates/users.html | 8 ++++++++ crates/presentation/src/forms.rs | 2 ++ crates/presentation/src/handlers/html.rs | 12 ++++++++++-- 4 files changed, 26 insertions(+), 2 deletions(-) diff --git a/crates/adapters/template-askama/templates/following.html b/crates/adapters/template-askama/templates/following.html index 9339899..23bc409 100644 --- a/crates/adapters/template-askama/templates/following.html +++ b/crates/adapters/template-askama/templates/following.html @@ -4,6 +4,12 @@ {% if let Some(err) = error %}

{{ err }}

{% endif %} +
+ + + + +
{% if actors.is_empty() %}

Not following anyone yet. Follow remote users from your profile page.

{% else %} diff --git a/crates/adapters/template-askama/templates/users.html b/crates/adapters/template-askama/templates/users.html index 6142e7b..d928375 100644 --- a/crates/adapters/template-askama/templates/users.html +++ b/crates/adapters/template-askama/templates/users.html @@ -2,6 +2,14 @@ {% block content %}

Members

+ {% if let Some(viewer_id) = ctx.user_id %} + + {% endif %} {% for user in users %}
{{ user.initial }}
diff --git a/crates/presentation/src/forms.rs b/crates/presentation/src/forms.rs index 3753df4..c32f71c 100644 --- a/crates/presentation/src/forms.rs +++ b/crates/presentation/src/forms.rs @@ -85,6 +85,8 @@ pub struct FollowForm { pub handle: String, #[serde(rename = "_csrf", default)] pub csrf_token: String, + #[serde(default)] + pub redirect_after: Option, } #[derive(Deserialize)] diff --git a/crates/presentation/src/handlers/html.rs b/crates/presentation/src/handlers/html.rs index e196744..a9a3acf 100644 --- a/crates/presentation/src/handlers/html.rs +++ b/crates/presentation/src/handlers/html.rs @@ -718,12 +718,20 @@ pub async fn follow_remote_user( if crate::csrf::mismatch(&csrf, &form.csrf_token) { return StatusCode::FORBIDDEN.into_response(); } + let redirect_base = form + .redirect_after + .as_deref() + .filter(|u| u.starts_with('/') && !u.starts_with("//")) + .unwrap_or(&format!("/users/{}", profile_user_uuid)) + .to_string(); + match state.ap_service.follow(user_id.value(), &form.handle).await { - Ok(()) => Redirect::to(&format!("/users/{}", profile_user_uuid)).into_response(), + Ok(()) => Redirect::to(&redirect_base).into_response(), Err(e) => { tracing::error!("follow error: {:?}", e); let msg = encode_error(&e.to_string()); - Redirect::to(&format!("/users/{}?error={}", profile_user_uuid, msg)).into_response() + let sep = if redirect_base.contains('?') { '&' } else { '?' }; + Redirect::to(&format!("{}{}error={}", redirect_base, sep, msg)).into_response() } } }