Compare commits
No commits in common. "a46390d110e8efbbe9f0cd2ab36cecea4b080747" and "6a228cfd5ed98877cd2b0e419d0bcff6894207e0" have entirely different histories.
a46390d110
...
6a228cfd5e
10
Cargo.lock
generated
10
Cargo.lock
generated
@ -2910,7 +2910,7 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "letterbox"
|
name = "letterbox"
|
||||||
version = "0.0.131"
|
version = "0.0.130"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"build-info",
|
"build-info",
|
||||||
"build-info-build",
|
"build-info-build",
|
||||||
@ -2936,7 +2936,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "letterbox-server"
|
name = "letterbox-server"
|
||||||
version = "0.0.131"
|
version = "0.0.130"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"ammonia",
|
"ammonia",
|
||||||
"anyhow",
|
"anyhow",
|
||||||
@ -3457,7 +3457,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "notmuch"
|
name = "notmuch"
|
||||||
version = "0.0.131"
|
version = "0.0.130"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"itertools 0.10.5",
|
"itertools 0.10.5",
|
||||||
"log",
|
"log",
|
||||||
@ -4252,7 +4252,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "procmail2notmuch"
|
name = "procmail2notmuch"
|
||||||
version = "0.0.131"
|
version = "0.0.130"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
]
|
]
|
||||||
@ -5331,7 +5331,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "shared"
|
name = "shared"
|
||||||
version = "0.0.131"
|
version = "0.0.130"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"build-info",
|
"build-info",
|
||||||
"notmuch",
|
"notmuch",
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "notmuch"
|
name = "notmuch"
|
||||||
version = "0.0.131"
|
version = "0.0.130"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "procmail2notmuch"
|
name = "procmail2notmuch"
|
||||||
version = "0.0.131"
|
version = "0.0.130"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "letterbox-server"
|
name = "letterbox-server"
|
||||||
version = "0.0.131"
|
version = "0.0.130"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
default-run = "letterbox-server"
|
default-run = "letterbox-server"
|
||||||
|
|
||||||
|
|||||||
@ -27,6 +27,7 @@ use lol_html::{
|
|||||||
use maplit::{hashmap, hashset};
|
use maplit::{hashmap, hashset};
|
||||||
use regex::Regex;
|
use regex::Regex;
|
||||||
use reqwest::StatusCode;
|
use reqwest::StatusCode;
|
||||||
|
use rocket::response::status;
|
||||||
use scraper::{Html, Selector};
|
use scraper::{Html, Selector};
|
||||||
use sqlx::types::time::PrimitiveDateTime;
|
use sqlx::types::time::PrimitiveDateTime;
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "shared"
|
name = "shared"
|
||||||
version = "0.0.131"
|
version = "0.0.130"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
[package]
|
[package]
|
||||||
version = "0.0.131"
|
version = "0.0.130"
|
||||||
name = "letterbox"
|
name = "letterbox"
|
||||||
repository = "https://github.com/seed-rs/seed-quickstart"
|
repository = "https://github.com/seed-rs/seed-quickstart"
|
||||||
authors = ["Bill Thiede <git@xinu.tv>"]
|
authors = ["Bill Thiede <git@xinu.tv>"]
|
||||||
|
|||||||
@ -92,7 +92,6 @@ pub fn view(model: &Model) -> Node<Msg> {
|
|||||||
"bg-black",
|
"bg-black",
|
||||||
"text-white",
|
"text-white",
|
||||||
"lg:flex-nowrap",
|
"lg:flex-nowrap",
|
||||||
"w-full"
|
|
||||||
],
|
],
|
||||||
div![
|
div![
|
||||||
C!["w-full", "lg:w-48", "flex-none", "flex", "flex-col"],
|
C!["w-full", "lg:w-48", "flex-none", "flex", "flex-col"],
|
||||||
@ -101,7 +100,7 @@ pub fn view(model: &Model) -> Node<Msg> {
|
|||||||
],
|
],
|
||||||
reading_progress(model.read_completion_ratio),
|
reading_progress(model.read_completion_ratio),
|
||||||
div![
|
div![
|
||||||
C!["flex-auto", "flex", "flex-col"],
|
C!["flex-auto"],
|
||||||
view_header(&model.query, &model.refreshing_state, true),
|
view_header(&model.query, &model.refreshing_state, true),
|
||||||
content,
|
content,
|
||||||
view_header(&model.query, &model.refreshing_state, false),
|
view_header(&model.query, &model.refreshing_state, false),
|
||||||
@ -178,7 +177,7 @@ fn search_results(
|
|||||||
span![C!["text-xs"], pretty_authors(&r.authors)],
|
span![C!["text-xs"], pretty_authors(&r.authors)],
|
||||||
div![
|
div![
|
||||||
C!["flex", "flex-wrap", "justify-between"],
|
C!["flex", "flex-wrap", "justify-between"],
|
||||||
span![tags_chiclet(&tags)],
|
span![tags_chiclet(&tags, true)],
|
||||||
span![C!["text-sm"], datetime]
|
span![C!["text-sm"], datetime]
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
@ -198,7 +197,7 @@ fn set_title(title: &str) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TODO: unifiy tags_chiclet, removable_tags_chiclet, and tags inside news_post()
|
// TODO: unifiy tags_chiclet, removable_tags_chiclet, and tags inside news_post()
|
||||||
fn tags_chiclet(tags: &[String]) -> impl Iterator<Item = Node<Msg>> + '_ {
|
fn tags_chiclet(tags: &[String], is_mobile: bool) -> impl Iterator<Item = Node<Msg>> + '_ {
|
||||||
tags.iter().map(move |tag| {
|
tags.iter().map(move |tag| {
|
||||||
let hex = compute_color(tag);
|
let hex = compute_color(tag);
|
||||||
let style = style! {St::BackgroundColor=>hex};
|
let style = style! {St::BackgroundColor=>hex};
|
||||||
@ -214,7 +213,11 @@ fn tags_chiclet(tags: &[String]) -> impl Iterator<Item = Node<Msg>> + '_ {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn removable_tags_chiclet<'a>(thread_id: &'a str, tags: &'a [String]) -> Node<Msg> {
|
fn removable_tags_chiclet<'a>(
|
||||||
|
thread_id: &'a str,
|
||||||
|
tags: &'a [String],
|
||||||
|
is_mobile: bool,
|
||||||
|
) -> Node<Msg> {
|
||||||
div![
|
div![
|
||||||
C!["flex"],
|
C!["flex"],
|
||||||
tags.iter().map(move |tag| {
|
tags.iter().map(move |tag| {
|
||||||
@ -306,6 +309,131 @@ fn human_age(timestamp: i64) -> String {
|
|||||||
datetime
|
datetime
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn view_search_results(
|
||||||
|
query: &str,
|
||||||
|
results: &[FrontPageQuerySearchNodes],
|
||||||
|
count: usize,
|
||||||
|
pager: &FrontPageQuerySearchPageInfo,
|
||||||
|
selected_threads: &HashSet<String>,
|
||||||
|
) -> Node<Msg> {
|
||||||
|
if query.is_empty() {
|
||||||
|
set_title("all mail");
|
||||||
|
} else {
|
||||||
|
set_title(query);
|
||||||
|
}
|
||||||
|
let show_bulk_edit = !selected_threads.is_empty();
|
||||||
|
let all_checked = selected_threads.len() == results.len();
|
||||||
|
let partially_checked = !selected_threads.is_empty() && !all_checked;
|
||||||
|
let rows = results.iter().map(|r| {
|
||||||
|
let tid = r.thread.clone();
|
||||||
|
let check_tid = r.thread.clone();
|
||||||
|
let datetime = human_age(r.timestamp as i64);
|
||||||
|
let unread_idx = r.tags.iter().position(|e| e == &"unread");
|
||||||
|
let mut tags = r.tags.clone();
|
||||||
|
if let Some(idx) = unread_idx {
|
||||||
|
tags.remove(idx);
|
||||||
|
};
|
||||||
|
let subject = if r.subject.is_empty() {
|
||||||
|
"(no subject)"
|
||||||
|
} else {
|
||||||
|
&r.subject
|
||||||
|
};
|
||||||
|
tr![
|
||||||
|
IF!(unread_idx.is_some() => C!["NOTPORTED","unread"]),
|
||||||
|
td![label![
|
||||||
|
C!["NOTPORTED", "b-checkbox", "checkbox"],
|
||||||
|
input![attrs! {
|
||||||
|
At::Type=>"checkbox",
|
||||||
|
At::Checked=>selected_threads.contains(&tid).as_at_value(),
|
||||||
|
}],
|
||||||
|
span![C!["NOTPORTED", "check"]],
|
||||||
|
ev(Ev::Input, move |e| {
|
||||||
|
if let Some(input) = e
|
||||||
|
.target()
|
||||||
|
.as_ref()
|
||||||
|
.expect("failed to get reference to target")
|
||||||
|
.dyn_ref::<web_sys::HtmlInputElement>()
|
||||||
|
{
|
||||||
|
if input.checked() {
|
||||||
|
Msg::SelectionAddThread(check_tid)
|
||||||
|
} else {
|
||||||
|
Msg::SelectionRemoveThread(check_tid)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Msg::Noop
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
]],
|
||||||
|
td![
|
||||||
|
C!["NOTPORTED", "from", format!("corpus-{:?} ", r.corpus)],
|
||||||
|
a![
|
||||||
|
C!["NOTPORTED", "has-text-light", "text"],
|
||||||
|
attrs! {
|
||||||
|
At::Href => urls::thread(&tid)
|
||||||
|
},
|
||||||
|
pretty_authors(&r.authors),
|
||||||
|
IF!(r.total>1 => small![" ", r.total.to_string()]),
|
||||||
|
]
|
||||||
|
],
|
||||||
|
td![
|
||||||
|
C!["NOTPORTED", "subject"],
|
||||||
|
a![
|
||||||
|
tags_chiclet(&tags, false),
|
||||||
|
" ",
|
||||||
|
C!["NOTPORTED", "has-text-light", "text", "subject-link"],
|
||||||
|
attrs! {
|
||||||
|
At::Href => urls::thread(&tid)
|
||||||
|
},
|
||||||
|
&subject,
|
||||||
|
]
|
||||||
|
],
|
||||||
|
td![
|
||||||
|
C!["NOTPORTED", "date"],
|
||||||
|
a![
|
||||||
|
C!["NOTPORTED", "has-text-light", "text"],
|
||||||
|
attrs! {
|
||||||
|
At::Href => urls::thread(&tid)
|
||||||
|
},
|
||||||
|
datetime
|
||||||
|
]
|
||||||
|
]
|
||||||
|
]
|
||||||
|
});
|
||||||
|
return h1!["HELLO"];
|
||||||
|
div![
|
||||||
|
C!["flex"],
|
||||||
|
search_toolbar(count, pager, show_bulk_edit),
|
||||||
|
div![
|
||||||
|
thead![tr![
|
||||||
|
th![
|
||||||
|
C!["NOTPORTED", "edit"],
|
||||||
|
label![
|
||||||
|
C!["NOTPORTED", "b-checkbox", "checkbox"],
|
||||||
|
input![
|
||||||
|
IF!(partially_checked => C!["NOTPORTED","is-indeterminate"]),
|
||||||
|
attrs! {
|
||||||
|
At::Type=>"checkbox",
|
||||||
|
At::Checked=>all_checked.as_at_value(),
|
||||||
|
}
|
||||||
|
],
|
||||||
|
span![C!["NOTPORTED", "check"]],
|
||||||
|
ev(Ev::Click, move |_| if all_checked {
|
||||||
|
Msg::SelectionSetNone
|
||||||
|
} else {
|
||||||
|
Msg::SelectionSetAll
|
||||||
|
})
|
||||||
|
]
|
||||||
|
],
|
||||||
|
th![C!["NOTPORTED", "from"], "From"],
|
||||||
|
th![C!["NOTPORTED", "subject"], "Subject"],
|
||||||
|
th![C!["NOTPORTED", "date"], "Date"]
|
||||||
|
]],
|
||||||
|
tbody![rows]
|
||||||
|
],
|
||||||
|
search_toolbar(count, pager, show_bulk_edit)
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
fn search_toolbar(
|
fn search_toolbar(
|
||||||
count: usize,
|
count: usize,
|
||||||
pager: &FrontPageQuerySearchPageInfo,
|
pager: &FrontPageQuerySearchPageInfo,
|
||||||
@ -781,7 +909,7 @@ fn thread(
|
|||||||
div![
|
div![
|
||||||
C!["p-4", "lg:p-0"],
|
C!["p-4", "lg:p-0"],
|
||||||
h3![C!["text-xl"], subject],
|
h3![C!["text-xl"], subject],
|
||||||
span![removable_tags_chiclet(&thread.thread_id, &tags)],
|
span![removable_tags_chiclet(&thread.thread_id, &tags, false)],
|
||||||
div![
|
div![
|
||||||
C!["pt-4", "gap-2", "flex", "justify-around"],
|
C!["pt-4", "gap-2", "flex", "justify-around"],
|
||||||
div![
|
div![
|
||||||
@ -894,7 +1022,7 @@ fn view_header(
|
|||||||
"All",
|
"All",
|
||||||
],
|
],
|
||||||
input![
|
input![
|
||||||
C!["grow", "pl-2", "text-black", "rounded-r"],
|
C!["grow", "pl-4", "text-black", "rounded-r"],
|
||||||
attrs! {
|
attrs! {
|
||||||
At::Placeholder => "Search";
|
At::Placeholder => "Search";
|
||||||
At::AutoFocus => auto_focus_search.as_at_value();
|
At::AutoFocus => auto_focus_search.as_at_value();
|
||||||
@ -1030,7 +1158,7 @@ fn news_post(post: &ShowThreadQueryThreadOnNewsPost, content_el: &ElRef<HtmlElem
|
|||||||
set_title(subject);
|
set_title(subject);
|
||||||
let read_thread_id = post.thread_id.clone();
|
let read_thread_id = post.thread_id.clone();
|
||||||
let unread_thread_id = post.thread_id.clone();
|
let unread_thread_id = post.thread_id.clone();
|
||||||
fn tag(tag: String) -> Node<Msg> {
|
fn tag(tag: String, is_mobile: bool) -> Node<Msg> {
|
||||||
let hex = compute_color(&tag);
|
let hex = compute_color(&tag);
|
||||||
let style = style! {St::BackgroundColor=>hex};
|
let style = style! {St::BackgroundColor=>hex};
|
||||||
let attrs = attrs! {
|
let attrs = attrs! {
|
||||||
@ -1055,7 +1183,7 @@ fn news_post(post: &ShowThreadQueryThreadOnNewsPost, content_el: &ElRef<HtmlElem
|
|||||||
div![
|
div![
|
||||||
C!["p-4", "lg:p-0"],
|
C!["p-4", "lg:p-0"],
|
||||||
h3![C!["text-xl"], subject],
|
h3![C!["text-xl"], subject],
|
||||||
span![tag(format!("News/{}", post.slug))],
|
span![tag(format!("News/{}", post.slug), false)],
|
||||||
div![
|
div![
|
||||||
C!["pt-4", "gap-2", "flex", "justify-around"],
|
C!["pt-4", "gap-2", "flex", "justify-around"],
|
||||||
div![
|
div![
|
||||||
@ -1195,7 +1323,7 @@ fn render_news_post_header(post: &ShowThreadQueryThreadOnNewsPost) -> Node<Msg>
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
fn reading_progress(ratio: f64) -> Node<Msg> {
|
fn reading_progress(ratio: f64) -> Node<Msg> {
|
||||||
return vid
|
return div![];
|
||||||
let percent = ratio * 100.;
|
let percent = ratio * 100.;
|
||||||
info!("percent {percent}");
|
info!("percent {percent}");
|
||||||
div![
|
div![
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user