forked from alemi/upub
feat: routing under /web, scroll only tl
This commit is contained in:
parent
639a982bd0
commit
268265e34a
3 changed files with 52 additions and 38 deletions
|
@ -20,6 +20,15 @@
|
||||||
max-height: 2em;
|
max-height: 2em;
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
}
|
}
|
||||||
|
div.boxscroll {
|
||||||
|
max-height: calc(100vh - 8rem);
|
||||||
|
overflow-y: scroll;
|
||||||
|
}
|
||||||
|
@media screen and (max-width: 786px) {
|
||||||
|
div.boxscroll {
|
||||||
|
max-height: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
table.align {
|
table.align {
|
||||||
line-height: 1rem;
|
line-height: 1rem;
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,9 +3,10 @@ use std::sync::Arc;
|
||||||
use apb::{target::Addressed, Activity, ActivityMut, Actor, Base, Collection, Object, ObjectMut};
|
use apb::{target::Addressed, Activity, ActivityMut, Actor, Base, Collection, Object, ObjectMut};
|
||||||
use dashmap::DashMap;
|
use dashmap::DashMap;
|
||||||
use leptos::{leptos_dom::logging::console_log, *};
|
use leptos::{leptos_dom::logging::console_log, *};
|
||||||
use leptos_router::use_params_map;
|
use leptos_router::*;
|
||||||
|
|
||||||
pub const BASE_URL: &str = "https://feditest.alemi.dev";
|
pub const URL_BASE: &str = "https://feditest.alemi.dev";
|
||||||
|
pub const URL_PREFIX: &str = "/web";
|
||||||
|
|
||||||
#[derive(Debug, serde::Serialize)]
|
#[derive(Debug, serde::Serialize)]
|
||||||
struct LoginForm {
|
struct LoginForm {
|
||||||
|
@ -23,7 +24,7 @@ pub fn LoginBox(
|
||||||
view! {
|
view! {
|
||||||
<div>
|
<div>
|
||||||
<div class="w-100" class:hidden=move || { rx.get().unwrap_or_default().is_empty() }>
|
<div class="w-100" class:hidden=move || { rx.get().unwrap_or_default().is_empty() }>
|
||||||
"Hello "<a href="/users/test" >test</a>
|
"Hello "<a href="/web/users/test" >test</a>
|
||||||
<input style="float:right" type="submit" value="logout" on:click=move |_| {
|
<input style="float:right" type="submit" value="logout" on:click=move |_| {
|
||||||
tx.set(None);
|
tx.set(None);
|
||||||
} />
|
} />
|
||||||
|
@ -38,7 +39,7 @@ pub fn LoginBox(
|
||||||
let password = password_ref.get().map(|x| x.value()).unwrap_or("".into());
|
let password = password_ref.get().map(|x| x.value()).unwrap_or("".into());
|
||||||
spawn_local(async move {
|
spawn_local(async move {
|
||||||
let auth = reqwest::Client::new()
|
let auth = reqwest::Client::new()
|
||||||
.post(format!("{BASE_URL}/auth"))
|
.post(format!("{URL_BASE}/auth"))
|
||||||
.json(&LoginForm { email, password })
|
.json(&LoginForm { email, password })
|
||||||
.send()
|
.send()
|
||||||
.await.unwrap()
|
.await.unwrap()
|
||||||
|
@ -66,7 +67,7 @@ pub fn PostBox(token: Signal<Option<String>>) -> impl IntoView {
|
||||||
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("".into());
|
||||||
reqwest::Client::new()
|
reqwest::Client::new()
|
||||||
.post(format!("{BASE_URL}/users/test/outbox"))
|
.post(format!("{URL_BASE}/users/test/outbox"))
|
||||||
.header("Authorization", format!("Bearer {}", token.get().unwrap_or_default()))
|
.header("Authorization", format!("Bearer {}", token.get().unwrap_or_default()))
|
||||||
.json(
|
.json(
|
||||||
&serde_json::Value::Object(serde_json::Map::default())
|
&serde_json::Value::Object(serde_json::Map::default())
|
||||||
|
@ -74,7 +75,7 @@ pub fn PostBox(token: Signal<Option<String>>) -> impl IntoView {
|
||||||
.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(apb::Node::links(vec![apb::target::PUBLIC.to_string()]))
|
||||||
.set_cc(apb::Node::links(vec![format!("{BASE_URL}/users/test/followers")]))
|
.set_cc(apb::Node::links(vec![format!("{URL_BASE}/users/test/followers")]))
|
||||||
)
|
)
|
||||||
.send()
|
.send()
|
||||||
.await.unwrap()
|
.await.unwrap()
|
||||||
|
@ -114,6 +115,7 @@ pub fn ActorBanner(object: serde_json::Value) -> impl IntoView {
|
||||||
<div><b>{id}</b></div>
|
<div><b>{id}</b></div>
|
||||||
},
|
},
|
||||||
serde_json::Value::Object(_) => {
|
serde_json::Value::Object(_) => {
|
||||||
|
let uid = object.id().unwrap_or_default().split('/').last().unwrap_or_default().to_string();
|
||||||
let avatar_url = object.icon().get().map(|x| x.url().id().unwrap_or_default()).unwrap_or_default();
|
let avatar_url = object.icon().get().map(|x| x.url().id().unwrap_or_default()).unwrap_or_default();
|
||||||
let display_name = object.name().unwrap_or_default().to_string();
|
let display_name = object.name().unwrap_or_default().to_string();
|
||||||
let username = object.preferred_username().unwrap_or_default().to_string();
|
let username = object.preferred_username().unwrap_or_default().to_string();
|
||||||
|
@ -126,7 +128,7 @@ pub fn ActorBanner(object: serde_json::Value) -> impl IntoView {
|
||||||
<td><b>{display_name}</b></td>
|
<td><b>{display_name}</b></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td class="top" ><small>{username}@{domain}</small></td>
|
<td class="top" ><a class="clean" href={format!("/web/users/{uid}")} ><small>{username}@{domain}</small></a></td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
|
@ -143,7 +145,7 @@ pub fn Actor() -> impl IntoView {
|
||||||
let params = use_params_map();
|
let params = use_params_map();
|
||||||
let actor = create_local_resource(move || params.get().get("id").cloned().unwrap_or_default(), |uid| {
|
let actor = create_local_resource(move || params.get().get("id").cloned().unwrap_or_default(), |uid| {
|
||||||
async move {
|
async move {
|
||||||
reqwest::get(format!("{BASE_URL}/users/{uid}"))
|
reqwest::get(format!("{URL_BASE}/users/{uid}"))
|
||||||
.await
|
.await
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.json::<serde_json::Value>()
|
.json::<serde_json::Value>()
|
||||||
|
@ -228,7 +230,7 @@ struct OmgReqwestErrorIsNotClonable(String);
|
||||||
pub fn Timeline(
|
pub fn Timeline(
|
||||||
token: Signal<Option<String>>,
|
token: Signal<Option<String>>,
|
||||||
) -> impl IntoView {
|
) -> impl IntoView {
|
||||||
let (timeline, set_timeline) = create_signal(format!("{BASE_URL}/inbox/page"));
|
let (timeline, set_timeline) = create_signal(format!("{URL_BASE}/inbox/page"));
|
||||||
let users : Arc<DashMap<String, serde_json::Value>> = Arc::new(DashMap::new());
|
let users : Arc<DashMap<String, serde_json::Value>> = Arc::new(DashMap::new());
|
||||||
let _users = users.clone(); // TODO i think there is syntactic sugar i forgot?
|
let _users = users.clone(); // TODO i think there is syntactic sugar i forgot?
|
||||||
let items = create_local_resource(move || timeline.get(), move |feed_url| {
|
let items = create_local_resource(move || timeline.get(), move |feed_url| {
|
||||||
|
@ -238,32 +240,34 @@ pub fn Timeline(
|
||||||
view! {
|
view! {
|
||||||
<div class="ml-1">
|
<div class="ml-1">
|
||||||
<TimelinePicker tx=set_timeline rx=timeline />
|
<TimelinePicker tx=set_timeline rx=timeline />
|
||||||
<ErrorBoundary fallback=move |err| view! { <p>{format!("{:?}", err.get())}</p> } >
|
<div class="boxscroll mt-1" >
|
||||||
{move || items.with(|x| match x {
|
<ErrorBoundary fallback=move |err| view! { <p>{format!("{:?}", err.get())}</p> } >
|
||||||
None => Ok(view! { <p>loading...</p> }.into_view()),
|
{move || items.with(|x| match x {
|
||||||
Some(data) => match data {
|
None => Ok(view! { <p>loading...</p> }.into_view()),
|
||||||
Err(e) => Err(OmgReqwestErrorIsNotClonable(e.to_string())),
|
Some(data) => match data {
|
||||||
Ok(values) => Ok(
|
Err(e) => Err(OmgReqwestErrorIsNotClonable(e.to_string())),
|
||||||
values
|
Ok(values) => Ok(
|
||||||
.iter()
|
values
|
||||||
.map(|object| {
|
.iter()
|
||||||
let actor = object.actor().extract().unwrap_or_else(||
|
.map(|object| {
|
||||||
serde_json::Value::String(object.actor().id().unwrap_or_default())
|
let actor = object.actor().extract().unwrap_or_else(||
|
||||||
);
|
serde_json::Value::String(object.actor().id().unwrap_or_default())
|
||||||
view! {
|
);
|
||||||
<div class="post-card ml-1 mr-1 mt-1">
|
view! {
|
||||||
<ActorBanner object=actor />
|
<div class="ml-1 mr-1 mt-1">
|
||||||
<Activity activity=object.clone() />
|
<ActorBanner object=actor />
|
||||||
</div>
|
<Activity activity=object.clone() />
|
||||||
<hr/ >
|
</div>
|
||||||
}
|
<hr/ >
|
||||||
})
|
}
|
||||||
.collect::<Vec<Fragment>>()
|
})
|
||||||
.into_view()
|
.collect::<Vec<Fragment>>()
|
||||||
),
|
.into_view()
|
||||||
}
|
),
|
||||||
})}
|
}
|
||||||
</ErrorBoundary>
|
})}
|
||||||
|
</ErrorBoundary>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,7 @@ use upub_web::{
|
||||||
Actor, LoginBox, PostBox, Timeline
|
Actor, LoginBox, PostBox, Timeline
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
_ = console_log::init_with_level(log::Level::Debug);
|
_ = console_log::init_with_level(log::Level::Debug);
|
||||||
console_error_panic_hook::set_once();
|
console_error_panic_hook::set_once();
|
||||||
|
@ -15,7 +16,7 @@ fn main() {
|
||||||
<nav class="w-100">
|
<nav class="w-100">
|
||||||
<p>
|
<p>
|
||||||
<code>μpub</code>
|
<code>μpub</code>
|
||||||
<small class="ml-1 mr-1" ><a class="clean" href="/" >micro social network, federated</a></small>
|
<small class="ml-1 mr-1" ><a class="clean" href="/web" >micro social network, federated</a></small>
|
||||||
/* TODO kinda jank with the float but whatever, will do for now */
|
/* TODO kinda jank with the float but whatever, will do for now */
|
||||||
<small style="float: right" ><a href="https://git.alemi.dev/upub.git" >src</a></small>
|
<small style="float: right" ><a href="https://git.alemi.dev/upub.git" >src</a></small>
|
||||||
</p>
|
</p>
|
||||||
|
@ -36,8 +37,8 @@ fn main() {
|
||||||
<Router>
|
<Router>
|
||||||
<main>
|
<main>
|
||||||
<Routes>
|
<Routes>
|
||||||
<Route path="/" view=move || view! { <Timeline token=cookie /> } />
|
<Route path="/web" view=move || view! { <Timeline token=cookie /> } />
|
||||||
<Route path="/users/:id" view=Actor />
|
<Route path="/web/users/:id" view=Actor />
|
||||||
// <Route path="/object/:id" view=Object />
|
// <Route path="/object/:id" view=Object />
|
||||||
</Routes>
|
</Routes>
|
||||||
</main>
|
</main>
|
||||||
|
|
Loading…
Reference in a new issue