1
0
Fork 0
forked from alemi/upub

feat(web): post box allows picking post privacy

This commit is contained in:
əlemi 2024-04-17 06:46:59 +02:00
parent b0ffc6187f
commit 562dc22320
Signed by: alemi
GPG key ID: A4895B84D311642C
3 changed files with 67 additions and 31 deletions

View file

@ -103,12 +103,12 @@ impl Uri {
pub struct Http; pub struct Http;
impl Http { impl Http {
pub async fn request<T: serde::de::DeserializeOwned>( pub async fn request<T: serde::ser::Serialize>(
method: reqwest::Method, method: reqwest::Method,
url: &str, url: &str,
data: Option<&serde_json::Value>, data: Option<&T>,
token: Signal<Option<String>> token: Signal<Option<String>>
) -> reqwest::Result<T> { ) -> reqwest::Result<reqwest::Response> {
let mut req = reqwest::Client::new() let mut req = reqwest::Client::new()
.request(method, url); .request(method, url);
@ -122,17 +122,20 @@ impl Http {
req.send() req.send()
.await? .await?
.error_for_status()? .error_for_status()
}
pub async fn fetch<T: serde::de::DeserializeOwned>(url: &str, token: Signal<Option<String>>) -> reqwest::Result<T> {
Self::request::<()>(reqwest::Method::GET, url, None, token)
.await?
.json::<T>() .json::<T>()
.await .await
} }
pub async fn fetch<T: serde::de::DeserializeOwned>(url: &str, token: Signal<Option<String>>) -> reqwest::Result<T> { pub async fn post<T: serde::ser::Serialize>(url: &str, data: &T, token: Signal<Option<String>>) -> reqwest::Result<()> {
Self::request(reqwest::Method::GET, url, None, token).await Self::request(reqwest::Method::POST, url, Some(data), token)
} .await?;
Ok(())
pub async fn post<T: serde::de::DeserializeOwned>(url: &str, data: &serde_json::Value, token: Signal<Option<String>>) -> reqwest::Result<T> {
Self::request(reqwest::Method::POST, url, Some(data), token).await
} }
} }

View file

@ -115,31 +115,64 @@ pub fn TimelineNavigation() -> impl IntoView {
} }
#[component] #[component]
pub fn PostBox() -> impl IntoView { pub fn PostBox(username: Signal<Option<String>>) -> impl IntoView {
let auth = use_context::<Signal<Option<String>>>().expect("missing auth context"); let auth = use_context::<Signal<Option<String>>>().expect("missing auth context");
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 content_ref: NodeRef<html::Textarea> = create_node_ref();
let public_ref: NodeRef<html::Input> = create_node_ref();
let followers_ref: NodeRef<html::Input> = create_node_ref();
view! { view! {
<div class:hidden=move || !auth.get().present() > <div class:hidden=move || !auth.get().present() >
<input class="w-100" type="text" node_ref=summary_ref placeholder="cw" /> <table class="align w-100">
<textarea class="w-100" node_ref=content_ref placeholder="leptos is kinda fun!" ></textarea> <tr>
<td><input type="checkbox" title="public" value="public" node_ref=public_ref /></td>
<td class="w-100"><input class="w-100" type="text" node_ref=summary_ref title="summary" /></td>
<td><input type="checkbox" title="followers" value="followers" node_ref=followers_ref checked /></td>
</tr>
<tr>
<td colspan="3">
<textarea rows="5" class="w-100" node_ref=content_ref placeholder="leptos is kinda fun!" ></textarea>
</td>
</tr>
<tr>
<td colspan="3">
<button class="w-100" type="button" on:click=move |_| { <button class="w-100" type="button" on:click=move |_| {
spawn_local(async move { spawn_local(async move {
let summary = summary_ref.get().map(|x| x.value()); let summary = summary_ref.get().map(|x| x.value());
let content = content_ref.get().map(|x| x.value()).unwrap_or("".into()); let content = content_ref.get().map(|x| x.value()).unwrap_or_default();
Http::post( let public = public_ref.get().map(|x| x.checked()).unwrap_or_default();
let followers = followers_ref.get().map(|x| x.checked()).unwrap_or_default();
match Http::post(
&format!("{URL_BASE}/users/test/outbox"), &format!("{URL_BASE}/users/test/outbox"),
&serde_json::Value::Object(serde_json::Map::default()) &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())
.set_content(Some(&content)) .set_content(Some(&content))
.set_to(apb::Node::links(vec![apb::target::PUBLIC.to_string()])) .set_to(
.set_cc(apb::Node::links(vec![format!("{URL_BASE}/users/test/followers")])), if public {
apb::Node::links(vec![apb::target::PUBLIC.to_string()])
} else { apb::Node::Empty }
)
.set_cc(
if followers {
apb::Node::links(vec![format!("{URL_BASE}/users/{}/followers", username.get().unwrap_or_default())])
} else { apb::Node::Empty }
),
auth auth
) )
.await.unwrap() .await
{
Err(e) => console_error(&format!("error posting note: {e}")),
Ok(()) => {
if let Some(x) = summary_ref.get() { x.set_value("") }
if let Some(x) = content_ref.get() { x.set_value("") }
},
}
}) })
} >post</button> } >post</button>
</td>
</tr>
</table>
</div> </div>
} }
} }

View file

@ -71,7 +71,7 @@ fn main() {
<hr class="mt-1 mb-1" /> <hr class="mt-1 mb-1" />
<TimelineNavigation /> <TimelineNavigation />
<hr class="mt-1 mb-1" /> <hr class="mt-1 mb-1" />
<PostBox /> <PostBox username=username />
</div> </div>
<div class="col-main" class:w-100=move || menu.get() > <div class="col-main" class:w-100=move || menu.get() >
<Routes> <Routes>