From 8b3dfffd3b907a639c4821e45cdd0b857dec4e9e Mon Sep 17 00:00:00 2001 From: Gabriel Kaszewski Date: Fri, 15 May 2026 00:04:54 +0200 Subject: [PATCH] feat: followers/following links on remote profile; render remote post content as HTML --- .../adapters/activitypub-base/src/service.rs | 2 ++ crates/adapters/postgres/src/remote_actor.rs | 2 +- crates/api-types/src/responses.rs | 2 ++ crates/domain/src/models/remote_actor.rs | 2 ++ crates/presentation/src/handlers/users.rs | 2 ++ .../components/remote-user-profile.tsx | 25 +++++++++++++++++++ thoughts-frontend/components/thought-card.tsx | 13 +++++++--- thoughts-frontend/lib/api.ts | 2 ++ 8 files changed, 46 insertions(+), 4 deletions(-) diff --git a/crates/adapters/activitypub-base/src/service.rs b/crates/adapters/activitypub-base/src/service.rs index c88aa1f..7c1ec3a 100644 --- a/crates/adapters/activitypub-base/src/service.rs +++ b/crates/adapters/activitypub-base/src/service.rs @@ -1398,6 +1398,8 @@ impl domain::ports::FederationActionPort for ActivityPubService { banner_url: actor.banner_url.as_ref().map(|u| u.to_string()), also_known_as: actor.also_known_as.clone(), outbox_url: Some(actor.outbox_url.to_string()), + followers_url: Some(actor.followers_url.to_string()), + following_url: Some(actor.following_url.to_string()), attachment: actor .attachment .iter() diff --git a/crates/adapters/postgres/src/remote_actor.rs b/crates/adapters/postgres/src/remote_actor.rs index d94fbb5..20239e8 100644 --- a/crates/adapters/postgres/src/remote_actor.rs +++ b/crates/adapters/postgres/src/remote_actor.rs @@ -45,6 +45,6 @@ impl RemoteActorRepository for PgRemoteActorRepository { "SELECT url,handle,display_name,inbox_url,shared_inbox_url,public_key,avatar_url,last_fetched_at FROM remote_actors WHERE url=$1" ).bind(url).fetch_optional(&self.pool).await .map_err(|e| DomainError::Internal(e.to_string())) - .map(|o| o.map(|r| RemoteActor { url: r.url, handle: r.handle, display_name: r.display_name, inbox_url: r.inbox_url, shared_inbox_url: r.shared_inbox_url, public_key: r.public_key, avatar_url: r.avatar_url, last_fetched_at: r.last_fetched_at, bio: None, banner_url: None, also_known_as: None, outbox_url: None, attachment: vec![] })) + .map(|o| o.map(|r| RemoteActor { url: r.url, handle: r.handle, display_name: r.display_name, inbox_url: r.inbox_url, shared_inbox_url: r.shared_inbox_url, public_key: r.public_key, avatar_url: r.avatar_url, last_fetched_at: r.last_fetched_at, bio: None, banner_url: None, also_known_as: None, outbox_url: None, followers_url: None, following_url: None, attachment: vec![] })) } } diff --git a/crates/api-types/src/responses.rs b/crates/api-types/src/responses.rs index 80254a8..f61a406 100644 --- a/crates/api-types/src/responses.rs +++ b/crates/api-types/src/responses.rs @@ -106,5 +106,7 @@ pub struct RemoteActorResponse { pub banner_url: Option, pub also_known_as: Option, pub outbox_url: Option, + pub followers_url: Option, + pub following_url: Option, pub attachment: Vec, } diff --git a/crates/domain/src/models/remote_actor.rs b/crates/domain/src/models/remote_actor.rs index 9ed6919..e9b9687 100644 --- a/crates/domain/src/models/remote_actor.rs +++ b/crates/domain/src/models/remote_actor.rs @@ -14,5 +14,7 @@ pub struct RemoteActor { pub banner_url: Option, pub also_known_as: Option, pub outbox_url: Option, + pub followers_url: Option, + pub following_url: Option, pub attachment: Vec<(String, String)>, } diff --git a/crates/presentation/src/handlers/users.rs b/crates/presentation/src/handlers/users.rs index 5b9d62c..85fd0b1 100644 --- a/crates/presentation/src/handlers/users.rs +++ b/crates/presentation/src/handlers/users.rs @@ -204,6 +204,8 @@ pub async fn lookup_handler( banner_url: actor.banner_url, also_known_as: actor.also_known_as, outbox_url: actor.outbox_url, + followers_url: actor.followers_url, + following_url: actor.following_url, attachment: actor .attachment .into_iter() diff --git a/thoughts-frontend/components/remote-user-profile.tsx b/thoughts-frontend/components/remote-user-profile.tsx index 6f7e05c..b46f998 100644 --- a/thoughts-frontend/components/remote-user-profile.tsx +++ b/thoughts-frontend/components/remote-user-profile.tsx @@ -133,6 +133,31 @@ export function RemoteUserProfile({ + {(actor.followersUrl || actor.followingUrl) && ( +
+ {actor.followersUrl && ( + + Followers + + )} + {actor.followingUrl && ( + + Following + + )} +
+ )} + {actor.alsoKnownAs && (

Also known as:{" "} diff --git a/thoughts-frontend/components/thought-card.tsx b/thoughts-frontend/components/thought-card.tsx index 0648af6..14afd31 100644 --- a/thoughts-frontend/components/thought-card.tsx +++ b/thoughts-frontend/components/thought-card.tsx @@ -152,9 +152,16 @@ export function ThoughtCard({ -

- {thought.content} -

+ {thought.author.local ? ( +

+ {thought.content} +

+ ) : ( +
+ )} {token && ( diff --git a/thoughts-frontend/lib/api.ts b/thoughts-frontend/lib/api.ts index 81631e6..b2d471a 100644 --- a/thoughts-frontend/lib/api.ts +++ b/thoughts-frontend/lib/api.ts @@ -30,6 +30,8 @@ export const RemoteActorSchema = z.object({ bannerUrl: z.string().nullable(), alsoKnownAs: z.string().nullable(), outboxUrl: z.string().nullable(), + followersUrl: z.string().nullable(), + followingUrl: z.string().nullable(), attachment: z.array(ProfileFieldSchema), }); export type RemoteActor = z.infer;