Compare commits
11 Commits
letterbox-
...
letterbox-
| Author | SHA1 | Date | |
|---|---|---|---|
| a96693004c | |||
| ed9fe11fbf | |||
| 09fb14a796 | |||
| 58a7936bba | |||
| cd0ee361f5 | |||
| 77bd5abe0d | |||
| 450c5496b3 | |||
| 4411e45a3c | |||
| e7d20896d5 | |||
| 32a1115abd | |||
| 4982057500 |
18
Cargo.lock
generated
18
Cargo.lock
generated
@@ -910,9 +910,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "console_log"
|
name = "console_log"
|
||||||
version = "0.1.2"
|
version = "0.1.4"
|
||||||
source = "sparse+https://git.z.xinu.tv/api/packages/wathiede/cargo/"
|
source = "sparse+https://git.z.xinu.tv/api/packages/wathiede/cargo/"
|
||||||
checksum = "e628484ff9348e6c256644436f215c0a9766867820da8cf161c567db1c877e32"
|
checksum = "d36495b7586d34322c3ffcff0e0d9d0b70f3a4ce88a9c199b3d8a01afb1debd7"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"log",
|
"log",
|
||||||
"wasm-bindgen",
|
"wasm-bindgen",
|
||||||
@@ -1620,9 +1620,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "flate2"
|
name = "flate2"
|
||||||
version = "1.0.35"
|
version = "1.1.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c936bfdafb507ebbf50b8074c54fa31c5be9a1e7e5f467dd659697041407d07c"
|
checksum = "11faaf5a5236997af9848be0bef4db95824b1d534ebc64d0f0c6cf3e67bd38dc"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"crc32fast",
|
"crc32fast",
|
||||||
"miniz_oxide",
|
"miniz_oxide",
|
||||||
@@ -2965,7 +2965,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "letterbox-notmuch"
|
name = "letterbox-notmuch"
|
||||||
version = "0.9.3"
|
version = "0.9.8"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"itertools 0.14.0",
|
"itertools 0.14.0",
|
||||||
"log",
|
"log",
|
||||||
@@ -2980,14 +2980,14 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "letterbox-procmail2notmuch"
|
name = "letterbox-procmail2notmuch"
|
||||||
version = "0.9.3"
|
version = "0.9.8"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "letterbox-server"
|
name = "letterbox-server"
|
||||||
version = "0.9.3"
|
version = "0.9.8"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"ammonia",
|
"ammonia",
|
||||||
"anyhow",
|
"anyhow",
|
||||||
@@ -3030,7 +3030,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "letterbox-shared"
|
name = "letterbox-shared"
|
||||||
version = "0.9.3"
|
version = "0.9.8"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"build-info",
|
"build-info",
|
||||||
"letterbox-notmuch",
|
"letterbox-notmuch",
|
||||||
@@ -3039,7 +3039,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "letterbox-web"
|
name = "letterbox-web"
|
||||||
version = "0.9.3"
|
version = "0.9.8"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"build-info",
|
"build-info",
|
||||||
"build-info-build",
|
"build-info-build",
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ authors = ["Bill Thiede <git@xinu.tv>"]
|
|||||||
edition = "2021"
|
edition = "2021"
|
||||||
license = "UNLICENSED"
|
license = "UNLICENSED"
|
||||||
publish = ["xinu"]
|
publish = ["xinu"]
|
||||||
version = "0.9.3"
|
version = "0.9.8"
|
||||||
repository = "https://git.z.xinu.tv/wathiede/letterbox"
|
repository = "https://git.z.xinu.tv/wathiede/letterbox"
|
||||||
|
|
||||||
[profile.dev]
|
[profile.dev]
|
||||||
|
|||||||
3
Justfile
3
Justfile
@@ -1,3 +1,6 @@
|
|||||||
|
export CARGO_INCREMENTAL := "0"
|
||||||
|
export RUSTFLAGS := "-D warnings"
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@echo "Run: just patch|minor|major"
|
@echo "Run: just patch|minor|major"
|
||||||
|
|
||||||
|
|||||||
@@ -48,8 +48,8 @@ urlencoding = "2.1.3"
|
|||||||
#xtracing = { path = "../../xtracing" }
|
#xtracing = { path = "../../xtracing" }
|
||||||
#xtracing = { git = "http://git-private.h.xinu.tv/wathiede/xtracing.git" }
|
#xtracing = { git = "http://git-private.h.xinu.tv/wathiede/xtracing.git" }
|
||||||
xtracing = { version = "0.3.0", registry = "xinu" }
|
xtracing = { version = "0.3.0", registry = "xinu" }
|
||||||
letterbox-notmuch = { version = "0.9.3", path = "../notmuch", registry = "xinu" }
|
letterbox-notmuch = { version = "0.9.8", path = "../notmuch", registry = "xinu" }
|
||||||
letterbox-shared = { version = "0.9.3", path = "../shared", registry = "xinu" }
|
letterbox-shared = { version = "0.9.8", path = "../shared", registry = "xinu" }
|
||||||
|
|
||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
build-info-build = "0.0.39"
|
build-info-build = "0.0.39"
|
||||||
|
|||||||
@@ -12,5 +12,5 @@ version.workspace = true
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
build-info = "0.0.39"
|
build-info = "0.0.39"
|
||||||
letterbox-notmuch = { version = "0.9.3", path = "../notmuch", registry = "xinu" }
|
letterbox-notmuch = { version = "0.9.8", path = "../notmuch", registry = "xinu" }
|
||||||
serde = { version = "1.0.147", features = ["derive"] }
|
serde = { version = "1.0.147", features = ["derive"] }
|
||||||
|
|||||||
@@ -33,8 +33,8 @@ wasm-bindgen = "=0.2.100"
|
|||||||
uuid = { version = "1.13.1", features = [
|
uuid = { version = "1.13.1", features = [
|
||||||
"js",
|
"js",
|
||||||
] } # direct dep to set js feature, prevents Rng issues
|
] } # direct dep to set js feature, prevents Rng issues
|
||||||
letterbox-shared = { version = "0.9.3", path = "../shared", registry = "xinu" }
|
letterbox-shared = { version = "0.9.8", path = "../shared", registry = "xinu" }
|
||||||
letterbox-notmuch = { version = "0.9.3", path = "../notmuch", registry = "xinu" }
|
letterbox-notmuch = { version = "0.9.8", path = "../notmuch", registry = "xinu" }
|
||||||
seed_hooks = { version = "0.4.0", registry = "xinu" }
|
seed_hooks = { version = "0.4.0", registry = "xinu" }
|
||||||
strum_macros = "0.27.1"
|
strum_macros = "0.27.1"
|
||||||
|
|
||||||
|
|||||||
@@ -18,6 +18,9 @@ fn main() {
|
|||||||
#[cfg(debug_assertions)]
|
#[cfg(debug_assertions)]
|
||||||
console_error_panic_hook::set_once();
|
console_error_panic_hook::set_once();
|
||||||
|
|
||||||
|
#[cfg(debug_assertions)]
|
||||||
|
let lvl = Level::Debug;
|
||||||
|
#[cfg(not(debug_assertions))]
|
||||||
let lvl = Level::Info;
|
let lvl = Level::Info;
|
||||||
console_log::init_with_level(lvl).expect("failed to initialize console logging");
|
console_log::init_with_level(lvl).expect("failed to initialize console logging");
|
||||||
// Mount the `app` to the element with the `id` "app".
|
// Mount the `app` to the element with the `id` "app".
|
||||||
|
|||||||
@@ -32,13 +32,12 @@ pub fn init(url: Url, orders: &mut impl Orders<Msg>) -> Model {
|
|||||||
if url.hash().is_none() {
|
if url.hash().is_none() {
|
||||||
orders.request_url(urls::search(unread_query(), 0));
|
orders.request_url(urls::search(unread_query(), 0));
|
||||||
} else {
|
} else {
|
||||||
orders.notify(subs::UrlRequested::new(url));
|
orders.request_url(url);
|
||||||
};
|
};
|
||||||
orders.stream(streams::window_event(Ev::Resize, |_| Msg::OnResize));
|
|
||||||
// TODO(wathiede): only do this while viewing the index? Or maybe add a new message that force
|
// TODO(wathiede): only do this while viewing the index? Or maybe add a new message that force
|
||||||
// 'notmuch new' on the server periodically?
|
// 'notmuch new' on the server periodically?
|
||||||
orders.stream(streams::interval(30_000, || Msg::RefreshStart));
|
orders.stream(streams::interval(30_000, || Msg::RefreshStart));
|
||||||
orders.subscribe(on_url_changed);
|
orders.subscribe(Msg::OnUrlChanged);
|
||||||
orders.stream(streams::window_event(Ev::Scroll, |_| Msg::WindowScrolled));
|
orders.stream(streams::window_event(Ev::Scroll, |_| Msg::WindowScrolled));
|
||||||
|
|
||||||
build_info::build_info!(fn bi);
|
build_info::build_info!(fn bi);
|
||||||
@@ -54,24 +53,21 @@ pub fn init(url: Url, orders: &mut impl Orders<Msg>) -> Model {
|
|||||||
server: None,
|
server: None,
|
||||||
},
|
},
|
||||||
catchup: None,
|
catchup: None,
|
||||||
|
last_url: Url::current(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_url_changed(uc: subs::UrlChanged) -> Msg {
|
fn on_url_changed(old: &Url, mut new: Url) -> Msg {
|
||||||
let mut url = uc.0;
|
let did_change = *old != new;
|
||||||
let href = document().location().unwrap().href().unwrap();
|
|
||||||
let origin = document().location().unwrap().origin().unwrap();
|
|
||||||
let current_url = &href[origin.len()..];
|
|
||||||
let did_change = current_url != url.to_string();
|
|
||||||
let mut messages = Vec::new();
|
let mut messages = Vec::new();
|
||||||
if did_change {
|
if did_change {
|
||||||
messages.push(Msg::ScrollToTop)
|
messages.push(Msg::ScrollToTop)
|
||||||
}
|
}
|
||||||
info!(
|
info!(
|
||||||
"url changed\nold '{current_url}'\nnew '{url}', history {}",
|
"url changed\nold '{old}'\nnew '{new}', history {}",
|
||||||
history().length().unwrap_or(0)
|
history().length().unwrap_or(0)
|
||||||
);
|
);
|
||||||
let hpp = url.remaining_hash_path_parts();
|
let hpp = new.remaining_hash_path_parts();
|
||||||
let msg = match hpp.as_slice() {
|
let msg = match hpp.as_slice() {
|
||||||
["t", tid] => Msg::ShowThreadRequest {
|
["t", tid] => Msg::ShowThreadRequest {
|
||||||
thread_id: tid.to_string(),
|
thread_id: tid.to_string(),
|
||||||
@@ -142,7 +138,7 @@ pub fn update(msg: Msg, model: &mut Model, orders: &mut impl Orders<Msg>) {
|
|||||||
orders.perform_cmd(async move { Msg::Refresh });
|
orders.perform_cmd(async move { Msg::Refresh });
|
||||||
}
|
}
|
||||||
Msg::Refresh => {
|
Msg::Refresh => {
|
||||||
orders.perform_cmd(async move { on_url_changed(subs::UrlChanged(Url::current())) });
|
orders.request_url(Url::current());
|
||||||
}
|
}
|
||||||
Msg::Reload => {
|
Msg::Reload => {
|
||||||
window()
|
window()
|
||||||
@@ -150,7 +146,10 @@ pub fn update(msg: Msg, model: &mut Model, orders: &mut impl Orders<Msg>) {
|
|||||||
.reload()
|
.reload()
|
||||||
.expect("failed to reload window");
|
.expect("failed to reload window");
|
||||||
}
|
}
|
||||||
Msg::OnResize => (),
|
Msg::OnUrlChanged(new_url) => {
|
||||||
|
orders.send_msg(on_url_changed(&model.last_url, new_url.0.clone()));
|
||||||
|
model.last_url = new_url.0;
|
||||||
|
}
|
||||||
|
|
||||||
Msg::NextPage => {
|
Msg::NextPage => {
|
||||||
match &model.context {
|
match &model.context {
|
||||||
@@ -676,6 +675,7 @@ pub struct Model {
|
|||||||
pub content_el: ElRef<HtmlElement>,
|
pub content_el: ElRef<HtmlElement>,
|
||||||
pub versions: Version,
|
pub versions: Version,
|
||||||
pub catchup: Option<Catchup>,
|
pub catchup: Option<Catchup>,
|
||||||
|
pub last_url: Url,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
@@ -741,8 +741,8 @@ pub enum Msg {
|
|||||||
Refresh,
|
Refresh,
|
||||||
// Tell the client to reload whole page from server
|
// Tell the client to reload whole page from server
|
||||||
Reload,
|
Reload,
|
||||||
// Window has changed size
|
// TODO: add GoToUrl
|
||||||
OnResize,
|
OnUrlChanged(subs::UrlChanged),
|
||||||
// Tell the server to update state
|
// Tell the server to update state
|
||||||
RefreshStart,
|
RefreshStart,
|
||||||
RefreshDone(Option<gloo_net::Error>),
|
RefreshDone(Option<gloo_net::Error>),
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ use chrono::{DateTime, Datelike, Duration, Local, Utc};
|
|||||||
use human_format::{Formatter, Scales};
|
use human_format::{Formatter, Scales};
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
use letterbox_shared::compute_color;
|
use letterbox_shared::compute_color;
|
||||||
use log::{debug, error};
|
use log::error;
|
||||||
use seed::{prelude::*, *};
|
use seed::{prelude::*, *};
|
||||||
use seed_hooks::{state_access::CloneState, topo, use_state, StateAccessEventHandlers};
|
use seed_hooks::{state_access::CloneState, topo, use_state, StateAccessEventHandlers};
|
||||||
use web_sys::{HtmlElement, HtmlInputElement};
|
use web_sys::{HtmlElement, HtmlInputElement};
|
||||||
@@ -93,13 +93,13 @@ pub fn view(model: &Model) -> Node<Msg> {
|
|||||||
} => {
|
} => {
|
||||||
if let Some(catchup) = &model.catchup {
|
if let Some(catchup) = &model.catchup {
|
||||||
catchup_view(
|
catchup_view(
|
||||||
thread(thread_data, open_messages, &model.content_el),
|
thread(thread_data, open_messages, &model.content_el, true),
|
||||||
&catchup.items,
|
&catchup.items,
|
||||||
model.read_completion_ratio,
|
model.read_completion_ratio,
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
normal_view(
|
normal_view(
|
||||||
thread(thread_data, open_messages, &model.content_el),
|
thread(thread_data, open_messages, &model.content_el, false),
|
||||||
&model.versions,
|
&model.versions,
|
||||||
&model.query,
|
&model.query,
|
||||||
&model.refreshing_state,
|
&model.refreshing_state,
|
||||||
@@ -114,13 +114,13 @@ pub fn view(model: &Model) -> Node<Msg> {
|
|||||||
} => {
|
} => {
|
||||||
if let Some(catchup) = &model.catchup {
|
if let Some(catchup) = &model.catchup {
|
||||||
catchup_view(
|
catchup_view(
|
||||||
news_post(post, &model.content_el),
|
news_post(post, &model.content_el, true),
|
||||||
&catchup.items,
|
&catchup.items,
|
||||||
model.read_completion_ratio,
|
model.read_completion_ratio,
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
normal_view(
|
normal_view(
|
||||||
news_post(post, &model.content_el),
|
news_post(post, &model.content_el, false),
|
||||||
&model.versions,
|
&model.versions,
|
||||||
&model.query,
|
&model.query,
|
||||||
&model.refreshing_state,
|
&model.refreshing_state,
|
||||||
@@ -199,9 +199,10 @@ fn catchup_view(
|
|||||||
"border-b",
|
"border-b",
|
||||||
"border-gray-500",
|
"border-gray-500",
|
||||||
"bg-black",
|
"bg-black",
|
||||||
|
"opacity-50",
|
||||||
],
|
],
|
||||||
div![
|
div![
|
||||||
C!["absolute", "right-4", "text-gray-500"],
|
C!["absolute", "top-0", "right-4", "text-gray-500", "p-4"],
|
||||||
span![i![C!["fas", "fa-x"]]],
|
span![i![C!["fas", "fa-x"]]],
|
||||||
ev(Ev::Click, move |_| Msg::CatchupExit)
|
ev(Ev::Click, move |_| Msg::CatchupExit)
|
||||||
],
|
],
|
||||||
@@ -210,7 +211,7 @@ fn catchup_view(
|
|||||||
format!("{} left ", items.iter().filter(|i| !i.seen).count(),)
|
format!("{} left ", items.iter().filter(|i| !i.seen).count(),)
|
||||||
]
|
]
|
||||||
],
|
],
|
||||||
div![C!["mt-12", "mb-4"], content],
|
div![C!["mt-12", "mb-20"], content],
|
||||||
div![
|
div![
|
||||||
C![
|
C![
|
||||||
"fixed",
|
"fixed",
|
||||||
@@ -224,6 +225,7 @@ fn catchup_view(
|
|||||||
"border-t",
|
"border-t",
|
||||||
"border-gray-500",
|
"border-gray-500",
|
||||||
"bg-black",
|
"bg-black",
|
||||||
|
"opacity-50",
|
||||||
],
|
],
|
||||||
button![
|
button![
|
||||||
tw_classes::button(),
|
tw_classes::button(),
|
||||||
@@ -1048,11 +1050,13 @@ fn render_attachements(
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: add cathup_mode:bool and hide elements when true
|
||||||
#[topo::nested]
|
#[topo::nested]
|
||||||
fn thread(
|
fn thread(
|
||||||
thread: &ShowThreadQueryThreadOnEmailThread,
|
thread: &ShowThreadQueryThreadOnEmailThread,
|
||||||
open_messages: &HashSet<String>,
|
open_messages: &HashSet<String>,
|
||||||
content_el: &ElRef<HtmlElement>,
|
content_el: &ElRef<HtmlElement>,
|
||||||
|
catchup_mode: bool,
|
||||||
) -> Node<Msg> {
|
) -> Node<Msg> {
|
||||||
// TODO(wathiede): show per-message subject if it changes significantly from top-level subject
|
// TODO(wathiede): show per-message subject if it changes significantly from top-level subject
|
||||||
let subject = if thread.subject.is_empty() {
|
let subject = if thread.subject.is_empty() {
|
||||||
@@ -1085,7 +1089,7 @@ fn thread(
|
|||||||
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)],
|
||||||
div![
|
IF!(!catchup_mode => div![
|
||||||
C!["pt-4", "gap-2", "flex", "justify-around"],
|
C!["pt-4", "gap-2", "flex", "justify-around"],
|
||||||
div![
|
div![
|
||||||
button![
|
button![
|
||||||
@@ -1123,13 +1127,13 @@ fn thread(
|
|||||||
Msg::GoToSearchResults
|
Msg::GoToSearchResults
|
||||||
])),
|
])),
|
||||||
]]
|
]]
|
||||||
],
|
]),
|
||||||
],
|
],
|
||||||
div![
|
div![
|
||||||
C!["lg:mt-4", "mail-thread"],
|
C!["lg:mt-4", "mail-thread"],
|
||||||
el_ref(content_el),
|
el_ref(content_el),
|
||||||
messages,
|
messages,
|
||||||
click_to_top()
|
IF!(!catchup_mode => click_to_top())
|
||||||
],
|
],
|
||||||
/* TODO(wathiede): plumb in orignal id
|
/* TODO(wathiede): plumb in orignal id
|
||||||
a![
|
a![
|
||||||
@@ -1348,7 +1352,13 @@ pub fn view_tags(tags: &Option<Vec<Tag>>) -> Node<Msg> {
|
|||||||
]
|
]
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
fn news_post(post: &ShowThreadQueryThreadOnNewsPost, content_el: &ElRef<HtmlElement>) -> Node<Msg> {
|
|
||||||
|
// TODO: add cathup_mode:bool and hide elements when true
|
||||||
|
fn news_post(
|
||||||
|
post: &ShowThreadQueryThreadOnNewsPost,
|
||||||
|
content_el: &ElRef<HtmlElement>,
|
||||||
|
catchup_mode: bool,
|
||||||
|
) -> Node<Msg> {
|
||||||
let subject = &post.title;
|
let subject = &post.title;
|
||||||
set_title(subject);
|
set_title(subject);
|
||||||
let read_thread_id = post.thread_id.clone();
|
let read_thread_id = post.thread_id.clone();
|
||||||
@@ -1379,7 +1389,7 @@ fn news_post(post: &ShowThreadQueryThreadOnNewsPost, content_el: &ElRef<HtmlElem
|
|||||||
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))],
|
||||||
div![
|
IF!(!catchup_mode => div![
|
||||||
C!["pt-4", "gap-2", "flex", "justify-around"],
|
C!["pt-4", "gap-2", "flex", "justify-around"],
|
||||||
div![
|
div![
|
||||||
button![
|
button![
|
||||||
@@ -1407,7 +1417,7 @@ fn news_post(post: &ShowThreadQueryThreadOnNewsPost, content_el: &ElRef<HtmlElem
|
|||||||
],
|
],
|
||||||
// Placeholder for symmetry with email view that has Spam button
|
// Placeholder for symmetry with email view that has Spam button
|
||||||
div![],
|
div![],
|
||||||
],
|
]),
|
||||||
],
|
],
|
||||||
div![
|
div![
|
||||||
C!["lg:mt-4"],
|
C!["lg:mt-4"],
|
||||||
@@ -1427,12 +1437,11 @@ fn news_post(post: &ShowThreadQueryThreadOnNewsPost, content_el: &ElRef<HtmlElem
|
|||||||
raw![&post.body]
|
raw![&post.body]
|
||||||
]
|
]
|
||||||
],
|
],
|
||||||
click_to_top(),
|
IF!(!catchup_mode => click_to_top()),
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
fn render_news_post_header(post: &ShowThreadQueryThreadOnNewsPost) -> Node<Msg> {
|
fn render_news_post_header(post: &ShowThreadQueryThreadOnNewsPost) -> Node<Msg> {
|
||||||
let from = &post.site;
|
let from = &post.site;
|
||||||
// TODO: move avatar/favicon stuff to the server side and and come up with a solution for emails
|
|
||||||
let id = post.thread_id.clone();
|
let id = post.thread_id.clone();
|
||||||
let is_unread = !post.is_read;
|
let is_unread = !post.is_read;
|
||||||
let url = &post.url;
|
let url = &post.url;
|
||||||
@@ -1540,7 +1549,6 @@ fn reading_progress(ratio: f64) -> Node<Msg> {
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
pub fn view_versions(versions: &Version) -> Node<Msg> {
|
pub fn view_versions(versions: &Version) -> Node<Msg> {
|
||||||
debug!("versions {versions:?}");
|
|
||||||
aside![
|
aside![
|
||||||
C!["p-2"],
|
C!["p-2"],
|
||||||
p![C!["uppercase", "font-bold"], "Versions"],
|
p![C!["uppercase", "font-bold"], "Versions"],
|
||||||
|
|||||||
Reference in New Issue
Block a user