Add a bit more structure to searching.
This commit is contained in:
parent
cb8b00f8d1
commit
4390d24492
110
web/src/lib.rs
110
web/src/lib.rs
@ -14,6 +14,8 @@ use seed::{prelude::*, *};
|
|||||||
use serde::de::Deserialize;
|
use serde::de::Deserialize;
|
||||||
use wasm_timer::Instant;
|
use wasm_timer::Instant;
|
||||||
|
|
||||||
|
const SEARCH_RESULTS_PER_PAGE: usize = 20;
|
||||||
|
|
||||||
// ------ ------
|
// ------ ------
|
||||||
// Init
|
// Init
|
||||||
// ------ ------
|
// ------ ------
|
||||||
@ -32,12 +34,23 @@ fn init(url: Url, orders: &mut impl Orders<Msg>) -> Model {
|
|||||||
orders.send_msg(Msg::ShowPrettyRequest(tid));
|
orders.send_msg(Msg::ShowPrettyRequest(tid));
|
||||||
}
|
}
|
||||||
Some("s") => {
|
Some("s") => {
|
||||||
query = url.next_hash_path_part().unwrap_or("").to_string();
|
query = url
|
||||||
orders.send_msg(Msg::SearchRequest(query.clone()));
|
.next_hash_path_part()
|
||||||
|
.map(|q| Url::decode_uri_component(q).unwrap_or("".to_string()))
|
||||||
|
.unwrap_or("".to_string());
|
||||||
|
orders.send_msg(Msg::SearchRequest {
|
||||||
|
query: query.to_string(),
|
||||||
|
page: 0,
|
||||||
|
results_per_page: SEARCH_RESULTS_PER_PAGE,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
p => {
|
p => {
|
||||||
log!(p);
|
log!(p);
|
||||||
orders.send_msg(Msg::SearchRequest("".to_string()));
|
orders.send_msg(Msg::SearchRequest {
|
||||||
|
query: "".to_string(),
|
||||||
|
page: 0,
|
||||||
|
results_per_page: SEARCH_RESULTS_PER_PAGE,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
orders.subscribe(|uc: subs::UrlChanged| {
|
orders.subscribe(|uc: subs::UrlChanged| {
|
||||||
@ -85,7 +98,11 @@ enum Msg {
|
|||||||
Noop,
|
Noop,
|
||||||
RefreshStart,
|
RefreshStart,
|
||||||
RefreshDone(Option<FetchError>),
|
RefreshDone(Option<FetchError>),
|
||||||
SearchRequest(String),
|
SearchRequest {
|
||||||
|
query: String,
|
||||||
|
page: usize,
|
||||||
|
results_per_page: usize,
|
||||||
|
},
|
||||||
SearchResult(fetch::Result<shared::SearchResult>),
|
SearchResult(fetch::Result<shared::SearchResult>),
|
||||||
ShowRequest(String),
|
ShowRequest(String),
|
||||||
ShowResult(fetch::Result<ThreadSet>),
|
ShowResult(fetch::Result<ThreadSet>),
|
||||||
@ -111,14 +128,18 @@ fn update(msg: Msg, model: &mut Model, orders: &mut impl Orders<Msg>) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
Msg::SearchRequest(query) => {
|
Msg::SearchRequest {
|
||||||
info!("searching for '{query}'");
|
query,
|
||||||
|
page,
|
||||||
|
results_per_page,
|
||||||
|
} => {
|
||||||
|
info!("searching for '{query}' pg {page} # / pg {results_per_page}");
|
||||||
model.query = query.clone();
|
model.query = query.clone();
|
||||||
let url = Url::new().set_hash_path(["s", &query]);
|
let url = Url::new().set_hash_path(["s", &query]);
|
||||||
orders.request_url(url);
|
orders.request_url(url);
|
||||||
orders
|
orders.skip().perform_cmd(async move {
|
||||||
.skip()
|
Msg::SearchResult(search_request(&query, page, results_per_page).await)
|
||||||
.perform_cmd(async move { Msg::SearchResult(search_request(&query).await) });
|
});
|
||||||
}
|
}
|
||||||
Msg::SearchResult(Ok(response_data)) => {
|
Msg::SearchResult(Ok(response_data)) => {
|
||||||
debug!("fetch ok {:#?}", response_data);
|
debug!("fetch ok {:#?}", response_data);
|
||||||
@ -160,12 +181,11 @@ fn update(msg: Msg, model: &mut Model, orders: &mut impl Orders<Msg>) {
|
|||||||
Msg::NextPage => {
|
Msg::NextPage => {
|
||||||
match &model.context {
|
match &model.context {
|
||||||
Context::Search(sr) => {
|
Context::Search(sr) => {
|
||||||
orders.send_msg(Msg::SearchRequest(format!(
|
orders.send_msg(Msg::SearchRequest {
|
||||||
"{}?page={}&results_per_page={}",
|
query: sr.query.clone(),
|
||||||
Url::encode_uri_component(&sr.query),
|
page: sr.page + 1,
|
||||||
sr.page + 1,
|
results_per_page: sr.results_per_page,
|
||||||
sr.results_per_page
|
});
|
||||||
)));
|
|
||||||
}
|
}
|
||||||
Context::Thread(_) => (), // do nothing (yet?)
|
Context::Thread(_) => (), // do nothing (yet?)
|
||||||
Context::None => (), // do nothing (yet?)
|
Context::None => (), // do nothing (yet?)
|
||||||
@ -174,12 +194,11 @@ fn update(msg: Msg, model: &mut Model, orders: &mut impl Orders<Msg>) {
|
|||||||
Msg::PreviousPage => {
|
Msg::PreviousPage => {
|
||||||
match &model.context {
|
match &model.context {
|
||||||
Context::Search(sr) => {
|
Context::Search(sr) => {
|
||||||
orders.send_msg(Msg::SearchRequest(format!(
|
orders.send_msg(Msg::SearchRequest {
|
||||||
"{}?page={}&results_per_page={}",
|
query: sr.query.clone(),
|
||||||
Url::encode_uri_component(&sr.query),
|
page: sr.page.saturating_sub(1),
|
||||||
sr.page.saturating_sub(1),
|
results_per_page: sr.results_per_page,
|
||||||
sr.results_per_page
|
});
|
||||||
)));
|
|
||||||
}
|
}
|
||||||
Context::Thread(_) => (), // do nothing (yet?)
|
Context::Thread(_) => (), // do nothing (yet?)
|
||||||
Context::None => (), // do nothing (yet?)
|
Context::None => (), // do nothing (yet?)
|
||||||
@ -188,8 +207,12 @@ fn update(msg: Msg, model: &mut Model, orders: &mut impl Orders<Msg>) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn search_request(query: &str) -> fetch::Result<shared::SearchResult> {
|
async fn search_request(
|
||||||
Request::new(api::search(query))
|
query: &str,
|
||||||
|
page: usize,
|
||||||
|
results_per_page: usize,
|
||||||
|
) -> fetch::Result<shared::SearchResult> {
|
||||||
|
Request::new(api::search(query, page, results_per_page))
|
||||||
.method(Method::Get)
|
.method(Method::Get)
|
||||||
.fetch()
|
.fetch()
|
||||||
.await?
|
.await?
|
||||||
@ -199,12 +222,15 @@ async fn search_request(query: &str) -> fetch::Result<shared::SearchResult> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
mod api {
|
mod api {
|
||||||
|
use seed::Url;
|
||||||
|
|
||||||
const BASE_URL: &str = "/api";
|
const BASE_URL: &str = "/api";
|
||||||
pub fn refresh() -> String {
|
pub fn refresh() -> String {
|
||||||
format!("{BASE_URL}/refresh")
|
format!("{BASE_URL}/refresh")
|
||||||
}
|
}
|
||||||
pub fn search(query: &str) -> String {
|
pub fn search(query: &str, page: usize, results_per_page: usize) -> String {
|
||||||
format!("{BASE_URL}/search/{query}")
|
let query = Url::encode_uri_component(query);
|
||||||
|
format!("{BASE_URL}/search/{query}?page={page}&results_per_page={results_per_page}")
|
||||||
}
|
}
|
||||||
pub fn show(tid: &str) -> String {
|
pub fn show(tid: &str) -> String {
|
||||||
format!("{BASE_URL}/show/{tid}")
|
format!("{BASE_URL}/show/{tid}")
|
||||||
@ -400,9 +426,11 @@ fn tags_chiclet(tags: &[String], is_mobile: bool) -> impl Iterator<Item = Node<M
|
|||||||
"replied" => span![classes, style, i![C!["fa-solid", "fa-reply"]]],
|
"replied" => span![classes, style, i![C!["fa-solid", "fa-reply"]]],
|
||||||
_ => span![classes, style, &tag],
|
_ => span![classes, style, &tag],
|
||||||
},
|
},
|
||||||
ev(Ev::Click, move |_| Msg::SearchRequest(
|
ev(Ev::Click, move |_| Msg::SearchRequest {
|
||||||
Url::encode_uri_component(format!("tag:{tag}"))
|
query: format!("tag:{tag}"),
|
||||||
)),
|
page: 0,
|
||||||
|
results_per_page: SEARCH_RESULTS_PER_PAGE,
|
||||||
|
})
|
||||||
]
|
]
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -621,12 +649,20 @@ fn view_header(query: &str, refresh_request: &RefreshingState) -> Node<Msg> {
|
|||||||
a![
|
a![
|
||||||
C!["navbar-item", "button"],
|
C!["navbar-item", "button"],
|
||||||
"Unread",
|
"Unread",
|
||||||
ev(Ev::Click, |_| Msg::SearchRequest("is:unread".to_string())),
|
ev(Ev::Click, |_| Msg::SearchRequest {
|
||||||
|
query: "is:unread".to_string(),
|
||||||
|
page: 0,
|
||||||
|
results_per_page: SEARCH_RESULTS_PER_PAGE,
|
||||||
|
}),
|
||||||
],
|
],
|
||||||
a![
|
a![
|
||||||
C!["navbar-item", "button"],
|
C!["navbar-item", "button"],
|
||||||
"All",
|
"All",
|
||||||
ev(Ev::Click, |_| Msg::SearchRequest("".to_string())),
|
ev(Ev::Click, |_| Msg::SearchRequest {
|
||||||
|
query: "".to_string(),
|
||||||
|
page: 0,
|
||||||
|
results_per_page: SEARCH_RESULTS_PER_PAGE,
|
||||||
|
}),
|
||||||
],
|
],
|
||||||
input![
|
input![
|
||||||
C!["navbar-item", "input"],
|
C!["navbar-item", "input"],
|
||||||
@ -635,12 +671,18 @@ fn view_header(query: &str, refresh_request: &RefreshingState) -> Node<Msg> {
|
|||||||
At::AutoFocus => true.as_at_value();
|
At::AutoFocus => true.as_at_value();
|
||||||
At::Value => query,
|
At::Value => query,
|
||||||
},
|
},
|
||||||
input_ev(Ev::Input, |q| Msg::SearchRequest(
|
input_ev(Ev::Input, |q| Msg::SearchRequest {
|
||||||
Url::encode_uri_component(q)
|
query: Url::encode_uri_component(q),
|
||||||
)),
|
page: 0,
|
||||||
|
results_per_page: SEARCH_RESULTS_PER_PAGE,
|
||||||
|
}),
|
||||||
// Resend search on enter.
|
// Resend search on enter.
|
||||||
keyboard_ev(Ev::KeyUp, move |e| if e.key_code() == 0x0d {
|
keyboard_ev(Ev::KeyUp, move |e| if e.key_code() == 0x0d {
|
||||||
Msg::SearchRequest(Url::encode_uri_component(query))
|
Msg::SearchRequest {
|
||||||
|
query: Url::encode_uri_component(query),
|
||||||
|
page: 0,
|
||||||
|
results_per_page: SEARCH_RESULTS_PER_PAGE,
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
Msg::Noop
|
Msg::Noop
|
||||||
}),
|
}),
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user