forked from alemi/upub
feat(web): mentions, dynamically resolved and shown
This commit is contained in:
parent
17f77c1769
commit
b9a25bc3d7
2 changed files with 48 additions and 8 deletions
|
@ -34,4 +34,5 @@ lazy_static = "1.4"
|
||||||
chrono = { version = "0.4", features = ["serde"] }
|
chrono = { version = "0.4", features = ["serde"] }
|
||||||
web-sys = { version = "0.3", features = ["Screen"] }
|
web-sys = { version = "0.3", features = ["Screen"] }
|
||||||
mdhtml = { path = "../mdhtml/" }
|
mdhtml = { path = "../mdhtml/" }
|
||||||
jrd = "0.1.0"
|
jrd = "0.1"
|
||||||
|
tld = "2.35"
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
use apb::{ActivityMut, Base, BaseMut, Object, ObjectMut};
|
use apb::{ActivityMut, Base, BaseMut, Object, ObjectMut};
|
||||||
|
|
||||||
use leptos::*;
|
use leptos::*;
|
||||||
use crate::prelude::*;
|
use leptos_use::DebounceOptions;
|
||||||
|
use crate::{prelude::*, WEBFINGER};
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, Default)]
|
#[derive(Debug, Clone, Copy, Default)]
|
||||||
pub struct ReplyControls {
|
pub struct ReplyControls {
|
||||||
|
@ -34,11 +35,34 @@ pub fn PostBox(advanced: WriteSignal<bool>) -> impl IntoView {
|
||||||
let reply = use_context::<ReplyControls>().expect("missing reply controls");
|
let reply = use_context::<ReplyControls>().expect("missing reply controls");
|
||||||
let (posting, set_posting) = create_signal(false);
|
let (posting, set_posting) = create_signal(false);
|
||||||
let (error, set_error) = create_signal(None);
|
let (error, set_error) = create_signal(None);
|
||||||
|
let (content, set_content) = create_signal("".to_string());
|
||||||
let summary_ref: NodeRef<html::Input> = create_node_ref();
|
let summary_ref: NodeRef<html::Input> = create_node_ref();
|
||||||
let content_ref: NodeRef<html::Textarea> = create_node_ref();
|
|
||||||
let public_ref: NodeRef<html::Input> = create_node_ref();
|
let public_ref: NodeRef<html::Input> = create_node_ref();
|
||||||
let followers_ref: NodeRef<html::Input> = create_node_ref();
|
let followers_ref: NodeRef<html::Input> = create_node_ref();
|
||||||
let private_ref: NodeRef<html::Input> = create_node_ref();
|
let private_ref: NodeRef<html::Input> = create_node_ref();
|
||||||
|
|
||||||
|
// TODO is this too abusive with resources? im even checking if TLD exists...
|
||||||
|
let mentions = create_local_resource(
|
||||||
|
move || content.get(),
|
||||||
|
move |c| async move {
|
||||||
|
let mut out = Vec::new();
|
||||||
|
for word in c.split(' ') {
|
||||||
|
if !word.starts_with('@') { break };
|
||||||
|
let stripped = word.replacen('@', "", 1);
|
||||||
|
if let Some((user, domain)) = stripped.split_once('@') {
|
||||||
|
if let Some(tld) = domain.split('.').last() {
|
||||||
|
if tld::exist(tld) {
|
||||||
|
if let Some(uid) = WEBFINGER.blocking_resolve(user, domain).await {
|
||||||
|
out.push(uid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
out
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
view! {
|
view! {
|
||||||
<div>
|
<div>
|
||||||
{move ||
|
{move ||
|
||||||
|
@ -51,13 +75,22 @@ pub fn PostBox(advanced: WriteSignal<bool>) -> impl IntoView {
|
||||||
on:click=move|_| reply.clear()
|
on:click=move|_| reply.clear()
|
||||||
title={format!("> {r} | ctx: {}", reply.context.get().unwrap_or_default())}
|
title={format!("> {r} | ctx: {}", reply.context.get().unwrap_or_default())}
|
||||||
>
|
>
|
||||||
"📨"
|
"✒️"
|
||||||
</span>
|
</span>
|
||||||
<small>{actor_strip}</small>
|
{actor_strip}
|
||||||
|
<small class="tiny ml-1">"["<a class="clean" title="remove reply" href="#" on:click=move |_| reply.clear() >reply</a>"]"</small>
|
||||||
</span>
|
</span>
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
{move ||
|
||||||
|
mentions.get()
|
||||||
|
.map(|x| x.into_iter().map(|u| match CACHE.get(&u) {
|
||||||
|
Some(u) => view! { <span class="nowrap"><span class="emoji mr-s ml-s">"📨"</span><ActorStrip object=u /></span> }.into_view(),
|
||||||
|
None => view! { <span class="nowrap"><span class="emoji mr-s ml-s">"📨"</span><a href={Uri::web(U::User, &u)}>{u}</a></span> }.into_view(),
|
||||||
|
})
|
||||||
|
.collect_view())
|
||||||
|
}
|
||||||
<table class="align w-100">
|
<table class="align w-100">
|
||||||
<tr>
|
<tr>
|
||||||
<td><input type="checkbox" on:input=move |ev| advanced.set(event_target_checked(&ev)) title="toggle advanced controls" /></td>
|
<td><input type="checkbox" on:input=move |ev| advanced.set(event_target_checked(&ev)) title="toggle advanced controls" /></td>
|
||||||
|
@ -65,7 +98,10 @@ pub fn PostBox(advanced: WriteSignal<bool>) -> impl IntoView {
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
<textarea rows="6" class="w-100" node_ref=content_ref title="content" placeholder="\n look at nothing\n what do you see?" ></textarea>
|
<textarea rows="6" class="w-100" title="content" placeholder="\n look at nothing\n what do you see?"
|
||||||
|
prop:value=content
|
||||||
|
on:input=move |ev| set_content.set(event_target_value(&ev))
|
||||||
|
></textarea>
|
||||||
|
|
||||||
<table class="align rev w-100">
|
<table class="align rev w-100">
|
||||||
<tr>
|
<tr>
|
||||||
|
@ -76,7 +112,7 @@ pub fn PostBox(advanced: WriteSignal<bool>) -> impl IntoView {
|
||||||
set_posting.set(true);
|
set_posting.set(true);
|
||||||
spawn_local(async move {
|
spawn_local(async move {
|
||||||
let summary = get_if_some(summary_ref);
|
let summary = get_if_some(summary_ref);
|
||||||
let content = content_ref.get().map(|x| x.value()).unwrap_or_default();
|
let content = content.get();
|
||||||
let mut cc_vec = Vec::new();
|
let mut cc_vec = Vec::new();
|
||||||
let mut to_vec = Vec::new();
|
let mut to_vec = Vec::new();
|
||||||
if get_checked(followers_ref) {
|
if get_checked(followers_ref) {
|
||||||
|
@ -92,6 +128,9 @@ pub fn PostBox(advanced: WriteSignal<bool>) -> impl IntoView {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
for mention in mentions.get().as_deref().unwrap_or(&[]) {
|
||||||
|
to_vec.push(mention.to_string());
|
||||||
|
}
|
||||||
let payload = serde_json::Value::Object(serde_json::Map::default())
|
let payload = serde_json::Value::Object(serde_json::Map::default())
|
||||||
.set_object_type(Some(apb::ObjectType::Note))
|
.set_object_type(Some(apb::ObjectType::Note))
|
||||||
.set_summary(summary.as_deref())
|
.set_summary(summary.as_deref())
|
||||||
|
@ -105,7 +144,7 @@ pub fn PostBox(advanced: WriteSignal<bool>) -> impl IntoView {
|
||||||
Ok(()) => {
|
Ok(()) => {
|
||||||
set_error.set(None);
|
set_error.set(None);
|
||||||
if let Some(x) = summary_ref.get() { x.set_value("") }
|
if let Some(x) = summary_ref.get() { x.set_value("") }
|
||||||
if let Some(x) = content_ref.get() { x.set_value("") }
|
set_content.set("".to_string());
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
set_posting.set(false);
|
set_posting.set(false);
|
||||||
|
|
Loading…
Reference in a new issue