diff --git a/web/src/components/activity.rs b/web/src/components/activity.rs index 0fee85b..2a9809d 100644 --- a/web/src/components/activity.rs +++ b/web/src/components/activity.rs @@ -1,16 +1,16 @@ use leptos::*; use crate::prelude::*; -use apb::{target::Addressed, Base, Activity, Object}; +use apb::{field::OptionalString, target::Addressed, Activity, Base, Object}; #[component] pub fn ActivityLine(activity: crate::Object) -> impl IntoView { - let object_id = activity.object().id().unwrap_or_default(); + let object_id = activity.object().id().str().unwrap_or_default(); let activity_url = activity.id().map(|x| view! { "↗" }); - let actor_id = activity.actor().id().unwrap_or_default(); + let actor_id = activity.actor().id().str().unwrap_or_default(); let actor = CACHE.get_or(&actor_id, serde_json::Value::String(actor_id.clone()).into()); let kind = activity.activity_type().unwrap_or(apb::ActivityType::Activity); let href = match kind { @@ -54,7 +54,7 @@ pub fn Item( Some(view! { {sep.clone()} }.into_view()), // everything else apb::ObjectType::Activity(t) => { - let object_id = item.object().id().unwrap_or_default(); + let object_id = item.object().id().str().unwrap_or_default(); let object = match t { apb::ActivityType::Create | apb::ActivityType::Announce => CACHE.get(&object_id).map(|obj| { diff --git a/web/src/components/object.rs b/web/src/components/object.rs index 7be75b0..c9d47ce 100644 --- a/web/src/components/object.rs +++ b/web/src/components/object.rs @@ -3,7 +3,7 @@ use std::sync::Arc; use leptos::*; use crate::{prelude::*, URL_SENSITIVE}; -use apb::{target::Addressed, ActivityMut, Base, Collection, CollectionMut, Document, Object, ObjectMut}; +use apb::{field::OptionalString, target::Addressed, ActivityMut, Base, Collection, CollectionMut, Document, Object, ObjectMut}; #[component] pub fn Attachment( @@ -13,7 +13,7 @@ pub fn Attachment( ) -> impl IntoView { let config = use_context::>().expect("missing config context"); let (expand, set_expand) = create_signal(false); - let href = object.url().id().unwrap_or_default(); + let href = object.url().id().str().unwrap_or_default(); let media_type = object.media_type() .unwrap_or("link") // TODO make it an Option rather than defaulting to link everywhere .to_string(); @@ -109,12 +109,12 @@ pub fn Attachment( pub fn Object(object: crate::Object) -> impl IntoView { let oid = object.id().unwrap_or_default().to_string(); let content = mdhtml::safe_html(object.content().unwrap_or_default()); - let author_id = object.attributed_to().id().unwrap_or_default(); + let author_id = object.attributed_to().id().str().unwrap_or_default(); let author = CACHE.get_or(&author_id, serde_json::Value::String(author_id.clone()).into()); let sensitive = object.sensitive().unwrap_or_default(); let addressed = object.addressed(); let public = addressed.iter().any(|x| x.as_str() == apb::target::PUBLIC); - let external_url = object.url().id().unwrap_or_else(|| oid.clone()); + let external_url = object.url().id().str().unwrap_or_else(|| oid.clone()); let attachments = object.attachment() .map(|x| view! { }) .collect_view(); @@ -175,7 +175,7 @@ pub fn Object(object: crate::Object) -> impl IntoView { - {object.in_reply_to().id().map(|reply| view! { + {object.in_reply_to().id().str().map(|reply| view! { reply })} diff --git a/web/src/components/post.rs b/web/src/components/post.rs index 9470d3c..6008632 100644 --- a/web/src/components/post.rs +++ b/web/src/components/post.rs @@ -1,4 +1,4 @@ -use apb::{ActivityMut, Base, BaseMut, Object, ObjectMut}; +use apb::{field::OptionalString, ActivityMut, Base, BaseMut, Object, ObjectMut}; use leptos::*; use crate::{prelude::*, WEBFINGER}; @@ -12,7 +12,7 @@ pub struct ReplyControls { impl ReplyControls { pub fn reply(&self, oid: &str) { if let Some(obj) = CACHE.get(oid) { - self.context.set(obj.context().id()); + self.context.set(obj.context().id().str()); self.reply_to.set(obj.id().ok().map(|x| x.to_string())); } } @@ -24,7 +24,7 @@ impl ReplyControls { } fn post_author(post_id: &str) -> Option { - let usr = CACHE.get(post_id)?.attributed_to().id()?; + let usr = CACHE.get(post_id)?.attributed_to().id().str()?; CACHE.get(&usr) } diff --git a/web/src/components/timeline.rs b/web/src/components/timeline.rs index c760412..5864008 100644 --- a/web/src/components/timeline.rs +++ b/web/src/components/timeline.rs @@ -1,6 +1,6 @@ use std::{collections::BTreeSet, pin::Pin, sync::Arc}; -use apb::{Activity, ActivityMut, Base, Object}; +use apb::{field::OptionalString, Activity, ActivityMut, Base, Object}; use leptos::*; use leptos_use::{signal_throttled, use_element_size, use_window_scroll, UseElementSizeReturn}; use crate::prelude::*; @@ -68,8 +68,8 @@ impl Timeline { feed.append(&mut older); self.feed.set(feed); - if let Some(next) = collection.next().id() { - self.next.set(next); + if let Ok(next) = collection.next().id() { + self.next.set(next.to_string()); } else { self.over.set(true); } @@ -86,9 +86,9 @@ pub fn TimelineRepliesRecursive(tl: Timeline, root: String) -> impl IntoView { .filter_map(|x| CACHE.get(&x)) .filter(|x| match x.object_type() { Ok(apb::ObjectType::Activity(apb::ActivityType::Create)) => { - let Some(oid) = x.object().id() else { return false; }; + let Some(oid) = x.object().id().str() else { return false; }; let Some(object) = CACHE.get(&oid) else { return false; }; - let Some(reply) = object.in_reply_to().id() else { return false; }; + let Some(reply) = object.in_reply_to().id().str() else { return false; }; reply == root }, Ok(apb::ObjectType::Activity(_)) => x.object().id().map(|o| o == root).unwrap_or(false), @@ -199,7 +199,7 @@ async fn process_activities(activities: Vec, auth: Auth) -> V // save embedded object if present if let Some(object) = activity.object().get() { // also fetch actor attributed to - if let Some(attributed_to) = object.attributed_to().id() { + if let Some(attributed_to) = object.attributed_to().id().str() { actors_seen.insert(attributed_to); } if let Ok(object_uri) = object.id() { @@ -208,7 +208,7 @@ async fn process_activities(activities: Vec, auth: Auth) -> V tracing::warn!("embedded object without id: {object:?}"); } } else { // try fetching it - if let Some(object_id) = activity.object().id() { + if let Some(object_id) = activity.object().id().str() { if !gonna_fetch.contains(&object_id) { let fetch_kind = match activity_type { apb::ActivityType::Follow => U::Actor, @@ -221,25 +221,25 @@ async fn process_activities(activities: Vec, auth: Auth) -> V } // save activity, removing embedded object - let object_id = activity.object().id(); - if let Ok(activity_id) = activity.id() { + let object_id = activity.object().id().str(); + if let Some(activity_id) = activity.id().str() { out.push(activity_id.to_string()); CACHE.put( activity_id.to_string(), Arc::new(activity.clone().set_object(apb::Node::maybe_link(object_id))) ); - } else if let Some(object_id) = activity.object().id() { + } else if let Some(object_id) = activity.object().id().str() { out.push(object_id); } - if let Some(uid) = activity.attributed_to().id() { + if let Some(uid) = activity.attributed_to().id().str() { if CACHE.get(&uid).is_none() && !gonna_fetch.contains(&uid) { gonna_fetch.insert(uid.clone()); sub_tasks.push(Box::pin(fetch_and_update(U::Actor, uid, auth))); } } - if let Some(uid) = activity.actor().id() { + if let Some(uid) = activity.actor().id().str() { if CACHE.get(&uid).is_none() && !gonna_fetch.contains(&uid) { gonna_fetch.insert(uid.clone()); sub_tasks.push(Box::pin(fetch_and_update(U::Actor, uid, auth))); @@ -267,8 +267,8 @@ async fn fetch_and_update_with_user(kind: U, id: String, auth: Auth) { fetch_and_update(kind, id.clone(), auth).await; if let Some(obj) = CACHE.get(&id) { if let Some(actor_id) = match kind { - U::Object => obj.attributed_to().id(), - U::Activity => obj.actor().id(), + U::Object => obj.attributed_to().id().str(), + U::Activity => obj.actor().id().str(), U::Actor | U::Context => None, } { fetch_and_update(U::Actor, actor_id, auth).await; diff --git a/web/src/components/user.rs b/web/src/components/user.rs index 82c69d7..fd731f4 100644 --- a/web/src/components/user.rs +++ b/web/src/components/user.rs @@ -1,14 +1,14 @@ use leptos::*; use crate::{prelude::*, DEFAULT_AVATAR_URL}; -use apb::{Activity, ActivityMut, Actor, Base, Object, ObjectMut}; +use apb::{field::OptionalString, Activity, ActivityMut, Actor, Base, Object, ObjectMut}; #[component] pub fn ActorStrip(object: crate::Object) -> impl IntoView { let actor_id = object.id().unwrap_or_default().to_string(); let username = object.preferred_username().unwrap_or_default().to_string(); let domain = object.id().unwrap_or_default().replace("https://", "").split('/').next().unwrap_or_default().to_string(); - let avatar = object.icon().get().map(|x| x.url().id().unwrap_or(DEFAULT_AVATAR_URL.into())).unwrap_or(DEFAULT_AVATAR_URL.into()); + let avatar = object.icon().get().map(|x| x.url().id().str().unwrap_or(DEFAULT_AVATAR_URL.into())).unwrap_or(DEFAULT_AVATAR_URL.into()); view! { {username}@{domain} @@ -25,7 +25,7 @@ pub fn ActorBanner(object: crate::Object) -> impl IntoView { serde_json::Value::Object(_) => { let uid = object.id().unwrap_or_default().to_string(); let uri = Uri::web(U::Actor, &uid); - let avatar_url = object.icon().get().map(|x| x.url().id().unwrap_or(DEFAULT_AVATAR_URL.into())).unwrap_or(DEFAULT_AVATAR_URL.into()); + let avatar_url = object.icon().get().map(|x| x.url().id().str().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 domain = object.id().unwrap_or_default().replace("https://", "").split('/').next().unwrap_or_default().to_string(); @@ -55,7 +55,7 @@ pub fn FollowRequestButtons(activity_id: String, actor_id: String) -> impl IntoV // TODO lmao what is going on with this double move / triple clone ??????????? let _activity_id = activity_id.clone(); let _actor_id = actor_id.clone(); - let from_actor = CACHE.get(&activity_id).map(|x| x.actor().id().unwrap_or_default()).unwrap_or_default(); + let from_actor = CACHE.get(&activity_id).map(|x| x.actor().id().str().unwrap_or_default()).unwrap_or_default(); let _from_actor = from_actor.clone(); if actor_id == auth.user_id() { Some(view! { diff --git a/web/src/config.rs b/web/src/config.rs index d5d44c2..41d96e9 100644 --- a/web/src/config.rs +++ b/web/src/config.rs @@ -61,9 +61,9 @@ impl FiltersConfig { let mut reply_filter = true; if - item.in_reply_to().id().is_some() || + item.in_reply_to().id().is_ok() || item.object().get().map(|x| - x.in_reply_to().id().is_some() + x.in_reply_to().id().is_ok() ).unwrap_or(false) { reply_filter = self.replies; diff --git a/web/src/page/object.rs b/web/src/page/object.rs index ca4d7cd..13fcb07 100644 --- a/web/src/page/object.rs +++ b/web/src/page/object.rs @@ -24,11 +24,11 @@ pub fn ObjectPage(tl: Timeline) -> impl IntoView { None => { let obj = Http::fetch::(&Uri::api(U::Object, &oid, true), auth).await.ok()?; let obj = Arc::new(obj); - if let Some(author) = obj.attributed_to().id() { + if let Ok(author) = obj.attributed_to().id() { if let Ok(user) = Http::fetch::( - &Uri::api(U::Actor, &author, true), auth + &Uri::api(U::Actor, author, true), auth ).await { - CACHE.put(Uri::full(U::Actor, &author), Arc::new(user)); + CACHE.put(Uri::full(U::Actor, author), Arc::new(user)); } } CACHE.put(Uri::full(U::Object, &oid), obj.clone()); diff --git a/web/src/page/user.rs b/web/src/page/user.rs index ffdce3f..68bcb9a 100644 --- a/web/src/page/user.rs +++ b/web/src/page/user.rs @@ -4,7 +4,7 @@ use leptos::*; use leptos_router::*; use crate::{prelude::*, DEFAULT_AVATAR_URL}; -use apb::{Base, Actor, ActivityMut, Object, ObjectMut}; +use apb::{field::OptionalString, ActivityMut, Actor, Base, Object, ObjectMut}; fn send_follow_request(target: String) { let auth = use_context::().expect("missing auth context"); @@ -72,8 +72,8 @@ pub fn UserPage(tl: Timeline) -> impl IntoView { }, 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 avatar_url = object.icon().get().map(|x| x.url().id().str().unwrap_or(DEFAULT_AVATAR_URL.into())).unwrap_or(DEFAULT_AVATAR_URL.into()); + let background_url = object.image().get().map(|x| x.url().id().str().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();