diff --git a/Cargo.lock b/Cargo.lock index d9a73ce..fd0ccf5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -980,6 +980,7 @@ dependencies = [ "notmuch", "seed", "serde", + "serde_json", "wasm-bindgen-test", ] @@ -1782,9 +1783,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.87" +version = "1.0.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ce777b7b150d76b9cf60d28b55f5847135a003f7d7350c6be7a773508ce7d45" +checksum = "cad406b69c91885b5107daf2c29572f6c8cdb3c66826821e286c533490c0bc76" dependencies = [ "itoa", "ryu", diff --git a/web/Cargo.toml b/web/Cargo.toml index cc5c328..5ddac7f 100644 --- a/web/Cargo.toml +++ b/web/Cargo.toml @@ -23,6 +23,7 @@ console_log = {git = "http://git-private.h.xinu.tv/wathiede/console_log.git"} serde = { version = "1.0.147", features = ["derive"] } notmuch = {path = "../notmuch"} itertools = "0.10.5" +serde_json = { version = "1.0.93", features = ["unbounded_depth"] } [package.metadata.wasm-pack.profile.release] wasm-opt = ['-Os'] diff --git a/web/index.html b/web/index.html index 62af437..44b6dd3 100644 --- a/web/index.html +++ b/web/index.html @@ -14,6 +14,7 @@ } .body { padding-bottom: 1em; + border: 1px red solid; } .error { background-color: red; @@ -30,6 +31,9 @@ iframe { } .index .subject { } +.index .date { + white-space: nowrap; +} diff --git a/web/src/lib.rs b/web/src/lib.rs index 3405036..6659383 100644 --- a/web/src/lib.rs +++ b/web/src/lib.rs @@ -7,6 +7,7 @@ use itertools::Itertools; use log::{debug, error, info, warn, Level}; use notmuch::{Content, Part, SearchSummary, Thread, ThreadNode, ThreadSet}; use seed::{prelude::*, *}; +use serde::de::Deserialize; // ------ ------ // Init @@ -113,7 +114,6 @@ 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() @@ -137,13 +137,17 @@ mod api { } async fn show_request(tid: &str) -> fetch::Result { - Request::new(api::show(tid)) + let b = Request::new(api::show(tid)) .method(Method::Get) .fetch() .await? .check_status()? - .json() - .await + .bytes() + .await?; + let mut deserializer = serde_json::Deserializer::from_slice(&b); + deserializer.disable_recursion_limit(); + Ok(ThreadSet::deserialize(&mut deserializer) + .map_err(|_| FetchError::JsonError(fetch::JsonError::Serde(JsValue::NULL)))?) } // ------ ------ @@ -279,16 +283,29 @@ fn tags_chiclet(tags: &[String]) -> impl Iterator> + '_ { fn pretty_authors(authors: &str) -> impl Iterator> + '_ { let authors = authors.split(','); - authors - .map(|author| { - span![ + /* + if authors.len() == 1 { + return authors.iter().filter_map(|author| { + Some(span![ attrs! { - At::Title => author}, - author.split_whitespace().nth(0) - ] + At::Title => author.trim()}, + author + ]) + }); + } + */ + + authors + .filter_map(|author| { + author.split_whitespace().nth(0).map(|first| { + span![ + attrs! { + At::Title => author.trim()}, + first + ] + }) }) - .into() - .iterleave(itertools::repeat_n(",", authors.len()).map(|c| span![c])) + .intersperse(span![", "]) } fn view_search_results(query: &str, search_results: &SearchSummary) -> Node { @@ -302,11 +319,10 @@ fn view_search_results(query: &str, search_results: &SearchSummary) -> Node tr![ td![ C!["from"], - //pretty_authors(&r.authors), - &r.authors, + pretty_authors(&r.authors), IF!(r.total>1 => small![" ", r.total.to_string()]), ], - td![C!["subject"], tags_chiclet(&r.tags), &r.subject], + td![C!["subject"], tags_chiclet(&r.tags), " ", &r.subject], td![C!["date"], &r.date_relative], ev(Ev::Click, move |_| Msg::ShowRequest(tid)), ] @@ -381,31 +397,38 @@ fn view_header(query: &str) -> Node { let query = query.to_string(); nav![ C!["navbar"], - a![ - C!["navbar-item", "button",], - "Unread", - ev(Ev::Click, |_| Msg::SearchRequest("is:unread".to_string())), - ], - a![ - C!["navbar-item", "button"], - "All", - ev(Ev::Click, |_| Msg::SearchRequest("".to_string())), - ], - input![ - C!["navbar-item", "input"], - attrs! { - At::Placeholder => "Search"; - At::AutoFocus => true.as_at_value(); - At::Value => query, - }, - input_ev(Ev::Input, Msg::SearchRequest), - // Resend search on enter. - keyboard_ev(Ev::KeyUp, move |e| if e.key_code() == 0x0d { - Msg::SearchRequest(query) - } else { - Msg::Noop - }), - ], + attrs! {At::Role=>"navigation"}, + div![ + C!["navbar-menu"], + div![ + C!["navbar-start"], + a![ + C!["navbar-item", "button",], + "Unread", + ev(Ev::Click, |_| Msg::SearchRequest("is:unread".to_string())), + ], + a![ + C!["navbar-item", "button"], + "All", + ev(Ev::Click, |_| Msg::SearchRequest("".to_string())), + ], + input![ + C!["navbar-item", "input"], + attrs! { + At::Placeholder => "Search"; + At::AutoFocus => true.as_at_value(); + At::Value => query, + }, + input_ev(Ev::Input, Msg::SearchRequest), + // Resend search on enter. + keyboard_ev(Ev::KeyUp, move |e| if e.key_code() == 0x0d { + Msg::SearchRequest(query) + } else { + Msg::Noop + }), + ] + ] + ] ] } @@ -417,11 +440,11 @@ fn view(model: &Model) -> Node { Context::Thread(thread_set) => view_thread(thread_set), Context::Search(search_results) => view_search_results(&model.query, search_results), }; - - section![ + div![section![ C!["section"], - div![C!["container"], view_header(&model.query), content] - ] + view_header(&model.query), + div![C!["container"], content] + ]] } // ------ ------