use std::sync::Arc; use leptos::*; use leptos_router::*; use crate::{prelude::*, DEFAULT_AVATAR_URL}; use apb::{Base, Actor, ActivityMut, Object, ObjectMut}; fn send_follow_request(target: String) { let auth = use_context::().expect("missing auth context"); spawn_local(async move { let payload = serde_json::Value::Object(serde_json::Map::default()) .set_activity_type(Some(apb::ActivityType::Follow)) .set_object(apb::Node::link(target.clone())) .set_to(apb::Node::links(vec![target])); if let Err(e) = Http::post(&auth.outbox(), &payload, auth).await { tracing::error!("failed sending follow request: {e}"); } }) } #[component] pub fn UserPage(tl: Timeline) -> impl IntoView { let params = use_params_map(); let auth = use_context::().expect("missing auth context"); let id = params.get() .get("id") .cloned() .unwrap_or_default(); let mut uid = id .replace("/web/objects/", "") .replacen('+', "https://", 1) .replace('@', "/"); if !uid.starts_with("http") { uid = format!("{URL_BASE}/web/objects/{uid}"); } let actor = create_local_resource(move || params.get().get("id").cloned().unwrap_or_default(), move |id| { async move { match CACHE.get(&Uri::full(FetchKind::User, &id)) { Some(x) => Some(x.clone()), None => { let user : serde_json::Value = Http::fetch(&Uri::api(FetchKind::User, &id, true), auth).await.ok()?; let user = Arc::new(user); CACHE.put(Uri::full(FetchKind::User, &id), user.clone()); Some(user) }, } } }); view! {
users::view "\u{1f5d8}"
{move || { let uid = uid.clone(); match actor.get() { None => view! {

loading...

}.into_view(), Some(None) => { view! {

loading failed"↗"

}.into_view() }, Some(Some(object)) => { let uid = object.id().unwrap_or_default().to_string(); let avatar_url = object.icon().get().map(|x| x.url().id().unwrap_or(DEFAULT_AVATAR_URL.into())).unwrap_or(DEFAULT_AVATAR_URL.into()); let background_url = object.image().get().map(|x| x.url().id().unwrap_or(DEFAULT_AVATAR_URL.into())).unwrap_or(DEFAULT_AVATAR_URL.into()); let display_name = object.name().unwrap_or_default().to_string(); let username = object.preferred_username().unwrap_or_default().to_string(); let summary = object.summary().unwrap_or_default().to_string(); let domain = object.id().unwrap_or_default().replace("https://", "").split('/').next().unwrap_or_default().to_string(); let actor_type = object.actor_type().unwrap_or(apb::ActorType::Person); let actor_type_tag = if actor_type == apb::ActorType::Person { None } else { Some(view! { "["{actor_type.as_ref().to_lowercase()}"]" } ) }; let created = object.published(); let following = object.following_count().unwrap_or(0); let followers = object.followers_count().unwrap_or(0); let statuses = object.statuses_count().unwrap_or(0); let tl_url = format!("{}/outbox/page", Uri::api(FetchKind::User, &id.clone(), false)); if !tl.next.get().starts_with(&tl_url) { tl.reset(tl_url); } let following_me = object.following_me().unwrap_or(false); let followed_by_me = object.followed_by_me().unwrap_or(false); let _uid = uid.clone(); view! {
{display_name}{actor_type_tag} {statuses}" ""\u{1f582}"
{username.clone()}@{domain} {following}" ""👥"
{followers}" ""📢"
{if followed_by_me { view! { following }.into_view() } else { view! { }.into_view() }} {if following_me { Some(view! { follows you }) } else { None }}

}.into_view() }, } }}
} }