diff --git a/web/index.html b/web/index.html
index edb1ba1..37663ac 100644
--- a/web/index.html
+++ b/web/index.html
@@ -16,9 +16,13 @@
.error {
background-color: red;
}
-.text_plain {
+.view-part-text-plain {
white-space: pre-line;
}
+iframe {
+ height: 100%;
+ width: 100%;
+}
diff --git a/web/src/lib.rs b/web/src/lib.rs
index b8d0ede..860f209 100644
--- a/web/src/lib.rs
+++ b/web/src/lib.rs
@@ -3,8 +3,8 @@
// but some rules are too "annoying" or are not applicable for your case.)
#![allow(clippy::wildcard_imports)]
-use log::{debug, error, info, Level};
-use notmuch::{Content, Part, SearchSummary, ThreadNode, ThreadSet};
+use log::{debug, error, info, warn, Level};
+use notmuch::{Content, Part, SearchSummary, Thread, ThreadNode, ThreadSet};
use seed::{prelude::*, *};
// ------ ------
@@ -13,14 +13,34 @@ use seed::{prelude::*, *};
// `init` describes what should happen when your app started.
fn init(url: Url, orders: &mut impl Orders) -> Model {
+ warn!("init called");
log!(url);
- orders.subscribe(|_: subs::UrlChanged| info!("url changed!"));
- orders
- .skip()
- .perform_cmd(async { Msg::SearchResult(search_request("*").await) });
+ let mut url = url.clone();
+ let mut query = "".to_string();
+ let hpp = url.next_hash_path_part();
+ log!(hpp);
+ match hpp {
+ Some("t") => {
+ let tid = url.next_hash_path_part().unwrap_or("").to_string();
+ orders.send_msg(Msg::ShowRequest(tid));
+ }
+ Some("s") => {
+ query = url.next_hash_path_part().unwrap_or("").to_string();
+ orders.send_msg(Msg::SearchRequest(query.clone()));
+ }
+ p => {
+ log!(p);
+ orders.send_msg(Msg::SearchRequest("".to_string()));
+ }
+ };
+ orders.subscribe(|uc: subs::UrlChanged| {
+ info!("uc {:#?}", uc);
+ });
+
+ info!("init query '{}'", query);
Model {
context: Context::None,
- query: "".to_string(),
+ query,
}
}
@@ -57,32 +77,34 @@ enum Msg {
fn update(msg: Msg, model: &mut Model, orders: &mut impl Orders) {
match msg {
Msg::Noop => {}
+
Msg::SearchRequest(query) => {
model.query = query.clone();
+ let url = Url::new().set_hash_path(["s", &query]);
+ orders.request_url(url);
orders
.skip()
.perform_cmd(async move { Msg::SearchResult(search_request(&query).await) });
}
-
Msg::SearchResult(Ok(response_data)) => {
debug!("fetch ok {:#?}", response_data);
model.context = Context::Search(response_data);
}
-
Msg::SearchResult(Err(fetch_error)) => {
error!("fetch failed {:?}", fetch_error);
}
- Msg::ShowRequest(query) => {
+
+ Msg::ShowRequest(tid) => {
+ let url = Url::new().set_hash_path(["t", &tid]);
+ orders.request_url(url);
orders
.skip()
- .perform_cmd(async move { Msg::ShowResult(show_request(&query).await) });
+ .perform_cmd(async move { Msg::ShowResult(show_request(&tid).await) });
}
-
Msg::ShowResult(Ok(response_data)) => {
debug!("fetch ok {:#?}", response_data);
model.context = Context::Thread(response_data);
}
-
Msg::ShowResult(Err(fetch_error)) => {
error!("fetch failed {:?}", fetch_error);
}
@@ -90,6 +112,7 @@ fn update(msg: Msg, model: &mut Model, orders: &mut impl Orders) {
}
async fn search_request(query: &str) -> fetch::Result {
+ info!("making search request for '{}'", query);
Request::new(api::search(query))
.method(Method::Get)
.fetch()
@@ -100,20 +123,20 @@ async fn search_request(query: &str) -> fetch::Result {
}
mod api {
- const BASE_URL: &str = "http://nixos-07:9345";
+ const BASE_URL: &str = "/api";
pub fn search(query: &str) -> String {
format!("{}/search/{}", BASE_URL, query)
}
- pub fn show(query: &str) -> String {
- format!("{}/show/{}", BASE_URL, query)
+ pub fn show(tid: &str) -> String {
+ format!("{}/show/{}", BASE_URL, tid)
}
pub fn original(message_id: &str) -> String {
format!("{}/original/{}", BASE_URL, message_id)
}
}
-async fn show_request(query: &str) -> fetch::Result {
- Request::new(api::show(query))
+async fn show_request(tid: &str) -> fetch::Result {
+ Request::new(api::show(tid))
.method(Method::Get)
.fetch()
.await?
@@ -180,11 +203,7 @@ fn view_part(part: &Part) -> Node {
"text/plain" => view_text_plain(&part.content),
"text/html" => {
if let Some(Content::String(html)) = &part.content {
- return div![
- C!["view-part-text-html"],
- div!["TEST"],
- iframe![Node::from_html(None, &html)]
- ];
+ return div![C!["view-part-text-html"], div!["TEST"], raw![&html]];
} else {
div![
C!["error"],
@@ -244,10 +263,12 @@ fn first_subject(thread: &ThreadNode) -> Option {
None
}
-fn view_search_results(search_results: &SearchSummary) -> Node {
+fn view_search_results(query: &str, search_results: &SearchSummary) -> Node {
+ seed::document().set_title(&format!("lb: {}", query));
let rows = search_results.0.iter().map(|r| {
let tid = r.thread.clone();
tr![
+ td![],
td![
&r.authors,
IF!(r.total>1 => small![" ", r.total.to_string()]),
@@ -258,7 +279,10 @@ fn view_search_results(search_results: &SearchSummary) -> Node {
ev(Ev::Click, move |_| Msg::ShowRequest(tid)),
]
});
- div![table![tr![th!["From"], th!["Subject"], th!["Date"]], rows]]
+ div![table![
+ tr![th!["tid"], th!["From"], th!["Subject"], th!["Date"]],
+ rows
+ ]]
}
fn view_thread(thread_set: &ThreadSet) -> Node {
@@ -266,14 +290,46 @@ fn view_thread(thread_set: &ThreadSet) -> Node {
let thread = &thread_set.0[0];
assert_eq!(thread.0.len(), 1);
let thread_node = &thread.0[0];
+ let subject = first_subject(&thread_node).unwrap_or("".to_string());
+ seed::document().set_title(&subject);
div![
- h1![first_subject(&thread_node)],
+ h1![subject],
a![
attrs! {At::Href=>api::original(&thread_node.0.as_ref().expect("message missing").id)},
"Original"
],
view_message(&thread_node),
- pre!["Add zippy for debug dump"] /* pre![format!("Thread: {:#?}", thread_set).replace(" ", " ")] */
+ pre![
+ "Add zippy for debug dump",
+ view_debug_thread_set(thread_set)
+ ] /* pre![format!("Thread: {:#?}", thread_set).replace(" ", " ")] */
+ ]
+}
+
+fn view_debug_thread_set(thread_set: &ThreadSet) -> Node {
+ ul![thread_set
+ .0
+ .iter()
+ .enumerate()
+ .map(|(i, t)| { li!["t", i, ": ", view_debug_thread(t),] })]
+}
+fn view_debug_thread(thread: &Thread) -> Node {
+ ul![thread
+ .0
+ .iter()
+ .enumerate()
+ .map(|(i, tn)| { li!["tn", i, ": ", view_debug_thread_node(tn),] })]
+}
+
+fn view_debug_thread_node(thread_node: &ThreadNode) -> Node {
+ ul![
+ IF!(thread_node.0.is_some()=>li!["tn id:", &thread_node.0.as_ref().unwrap().id]),
+ thread_node.1.iter().enumerate().map(|(i, tn)| li![
+ "tn",
+ i,
+ ": ",
+ view_debug_thread_node(tn)
+ ])
]
}
@@ -307,7 +363,7 @@ fn view(model: &Model) -> Node {
let content = match &model.context {
Context::None => div![h1!["Loading"]],
Context::Thread(thread_set) => view_thread(thread_set),
- Context::Search(search_results) => view_search_results(search_results),
+ Context::Search(search_results) => view_search_results(&model.query, search_results),
};
div![view_header(&model.query), content]
}