diff --git a/web/index.html b/web/index.html index 9aafeab3..cea29866 100644 --- a/web/index.html +++ b/web/index.html @@ -84,6 +84,12 @@ font-size: .6em; color: var(--secondary); } + span.nowrap { + white-space: nowrap; + text-overflow: ellipsis; + overflow: hidden; + display: block; + } hr.sep { z-index: 100; margin-top: 0; diff --git a/web/src/app.rs b/web/src/app.rs index 90d9cf1a..0a76836c 100644 --- a/web/src/app.rs +++ b/web/src/app.rs @@ -20,6 +20,9 @@ pub fn App() -> impl IntoView { let user_tl = Timeline::new(format!("{URL_BASE}/users/{}/outbox/page", username.get().unwrap_or_default())); let context_tl = Timeline::new(format!("{URL_BASE}/outbox/page")); + let reply_controls = ReplyControls::default(); + provide_context(reply_controls); + let screen_width = window().screen().map(|x| x.avail_width().unwrap_or_default()).unwrap_or_default(); let (menu, set_menu) = create_signal(screen_width <= 786); diff --git a/web/src/components/object.rs b/web/src/components/object.rs index 3a6bb390..dc02f473 100644 --- a/web/src/components/object.rs +++ b/web/src/components/object.rs @@ -1,5 +1,3 @@ -use std::sync::Arc; - use leptos::*; use crate::{prelude::*, URL_SENSITIVE}; @@ -127,7 +125,7 @@ pub fn Object(object: crate::Object) -> impl IntoView {
- +
@@ -199,14 +197,23 @@ pub fn LikeButton( } #[component] -pub fn ReplyButton(n: u64) -> impl IntoView { +pub fn ReplyButton(n: u64, target: String) -> impl IntoView { + let reply = use_context::().expect("missing reply controls context"); let comments = if n > 0 { Some(view! { {n} }) } else { None }; + let _target = target.clone(); // TODO ughhhh useless clones view! { - {comments}" 📨" + + {comments} + " 📨" + } } diff --git a/web/src/control.rs b/web/src/control.rs index 9602e2ee..9d02457c 100644 --- a/web/src/control.rs +++ b/web/src/control.rs @@ -1,4 +1,4 @@ -use apb::{ActivityMut, BaseMut, ObjectMut}; +use apb::{ActivityMut, Base, BaseMut, Object, ObjectMut}; use leptos::*; use crate::prelude::*; @@ -14,9 +14,35 @@ pub fn Navigator() -> impl IntoView { } } +#[derive(Debug, Clone, Copy, Default)] +pub struct ReplyControls { + pub context: RwSignal>, + pub reply_to: RwSignal>, +} + +impl ReplyControls { + pub fn reply(&self, oid: &str) { + if let Some(obj) = CACHE.get(oid) { + self.context.set(obj.context().id()); + self.reply_to.set(obj.id().map(|x| x.to_string())); + } + } + + pub fn clear(&self) { + self.context.set(None); + self.reply_to.set(None); + } +} + +fn post_author(post_id: &str) -> Option { + let usr = CACHE.get(post_id)?.attributed_to().id()?; + CACHE.get(&usr) +} + #[component] pub fn PostBox(username: Signal>, advanced: WriteSignal) -> impl IntoView { let auth = use_context::().expect("missing auth context"); + let reply = use_context::().expect("missing reply controls"); let (posting, set_posting) = create_signal(false); let (error, set_error) = create_signal(None); let summary_ref: NodeRef = create_node_ref(); @@ -26,6 +52,23 @@ pub fn PostBox(username: Signal>, advanced: WriteSignal) -> let private_ref: NodeRef = create_node_ref(); view! {
+ {move || + reply.reply_to.get().map(|r| { + let actor_strip = post_author(&r).map(|x| view! { }); + view! { + + {r} | ctx: {}", reply.context.get().unwrap_or_default())} + > + "📨" + + {actor_strip} + + } + }) + } @@ -58,6 +101,8 @@ pub fn PostBox(username: Signal>, advanced: WriteSignal) -> .set_object_type(Some(apb::ObjectType::Note)) .set_summary(summary.as_deref()) .set_content(Some(&content)) + .set_context(apb::Node::maybe_link(reply.context.get())) + .set_in_reply_to(apb::Node::maybe_link(reply.reply_to.get())) .set_to(to) .set_cc(cc); let target_url = format!("{URL_BASE}/users/test/outbox");