Compare commits

..

No commits in common. "ee9b6be95efd68d250c8989732d78f1c76e876aa" and "c7740811bfdab1a4481cbafbd3ce5f042387c9c6" have entirely different histories.

19 changed files with 7061 additions and 152 deletions

7061
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -1,8 +1,7 @@
[workspace]
resolver = "2"
#default-members = ["server"]
members = ["notmuch", "procmail2notmuch", "shared"]
#members = ["web", "server", "notmuch", "procmail2notmuch", "shared"]
default-members = ["server"]
members = ["web", "server", "notmuch", "procmail2notmuch", "shared"]
[profile.dev]
opt-level = 1

View File

@ -1,13 +1,9 @@
[package]
name = "letterbox-notmuch"
version = "0.1.0"
name = "notmuch"
version = "0.0.144"
edition = "2021"
exclude = ["/testdata"]
description = "Wrapper for calling notmuch cli"
license = "UNLICENSED"
repository = "https://git.z.xinu.tv/wathiede/letterbox"
publish = ["xinu"]
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
log = "0.4.14"

View File

@ -4,7 +4,7 @@ use std::{
time::Instant,
};
use letterbox_notmuch::Notmuch;
use notmuch::Notmuch;
use rayon::iter::{ParallelBridge, ParallelIterator};
#[test]

View File

@ -1,11 +1,7 @@
[package]
name = "letterbox-procmail2notmuch"
version = "0.1.0"
name = "procmail2notmuch"
version = "0.0.144"
edition = "2021"
description = "Tool for generating notmuch rules from procmail"
license = "UNLICENSED"
repository = "https://git.z.xinu.tv/wathiede/letterbox"
publish = ["xinu"]
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

View File

@ -1,12 +1,8 @@
[package]
name = "letterbox-server"
version = "0.1.0"
version = "0.0.144"
edition = "2021"
default-run = "letterbox-server"
description = "Backend for letterbox"
license = "UNLICENSED"
repository = "https://git.z.xinu.tv/wathiede/letterbox"
publish = ["xinu"]
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
@ -29,6 +25,7 @@ lol_html = "2.0.0"
mailparse = "0.16.0"
maplit = "1.0.2"
memmap = "0.7.0"
notmuch = { path = "../notmuch" }
opentelemetry = "0.28.0"
regex = "1.11.1"
reqwest = { version = "0.12.7", features = ["blocking"] }
@ -37,6 +34,7 @@ rocket_cors = "0.6.0"
scraper = "0.22.0"
serde = { version = "1.0.147", features = ["derive"] }
serde_json = "1.0.87"
shared = { path = "../shared" }
sqlx = { version = "0.8.2", features = ["postgres", "runtime-tokio", "time"] }
tantivy = { version = "0.22.0", optional = true }
thiserror = "2.0.0"
@ -47,8 +45,6 @@ urlencoding = "2.1.3"
#xtracing = { path = "../../xtracing" }
#xtracing = { git = "http://git-private.h.xinu.tv/wathiede/xtracing.git" }
xtracing = { version = "0.2.0", registry = "xinu" }
letterbox-notmuch = { version = "0.1.0", registry = "xinu" }
letterbox-shared = { version = "0.1.0", registry = "xinu" }
[build-dependencies]
build-info-build = "0.0.39"

View File

@ -1,13 +0,0 @@
select t.id, tt.tokid, tt.alias, length(t.token), t.token from (
select id, (ts_parse('default',
-- regexp_replace(
-- regexp_replace(summary, '<[^>]+>', ' ', 'g'),
-- '\s+',
-- ' ',
-- 'g'
-- )
summary
)).* from post) t
inner join ts_token_type('default') tt
on t.tokid = tt.tokid
where length(token) >= 2*1024;

View File

@ -1,21 +0,0 @@
use std::fs;
use url::Url;
fn main() -> anyhow::Result<()> {
println!("PWD: {}", std::env::current_dir()?.display());
let _url = "https://slashdot.org/story/25/01/24/1813201/walgreens-replaced-fridge-doors-with-smart-screens-its-now-a-200-million-fiasco?utm_source=rss1.0mainlinkanon&utm_medium=feed";
let _url = "https://hackaday.com/2025/01/24/hackaday-podcast-episode-305-caustic-clocks-practice-bones-and-brick-layers/";
let _url = "https://theonion.com/monster-devastated-to-see-film-depicting-things-he-told-guillermo-del-toro-in-confidence/";
let _url = "https://trofi.github.io/posts/330-another-nix-language-nondeterminism-example.html";
let _url = "https://blog.cloudflare.com/ddos-threat-report-for-2024-q4/";
let url = "https://trofi.github.io/posts/330-another-nix-language-nondeterminism-example.html";
let body = reqwest::blocking::get(url)?.text()?;
let output = "/tmp/h2md/output.html";
let inliner = css_inline::CSSInliner::options()
.base_url(Url::parse(url).ok())
.build();
let inlined = inliner.inline(&body)?;
fs::write(output, inlined)?;
Ok(())
}

View File

@ -8,7 +8,6 @@ use std::{error::Error, io::Cursor, str::FromStr};
use async_graphql::{extensions, http::GraphiQLSource, EmptySubscription, Schema};
use async_graphql_rocket::{GraphQLQuery, GraphQLRequest, GraphQLResponse};
use cacher::FilesystemCacher;
use letterbox_notmuch::{Notmuch, NotmuchError, ThreadSet};
#[cfg(feature = "tantivy")]
use letterbox_server::tantivy::TantivyConnection;
use letterbox_server::{
@ -17,6 +16,7 @@ use letterbox_server::{
graphql::{Attachment, GraphqlSchema, Mutation, QueryRoot},
nm::{attachment_bytes, cid_attachment_bytes},
};
use notmuch::{Notmuch, NotmuchError, ThreadSet};
use rocket::{
fairing::AdHoc,
http::{ContentType, Header},
@ -179,7 +179,7 @@ async fn graphql_request(
async fn main() -> Result<(), Box<dyn Error>> {
let _guard = xtracing::init(env!("CARGO_BIN_NAME"))?;
build_info::build_info!(fn bi);
info!("Build Info: {}", letterbox_shared::build_version(bi));
info!("Build Info: {}", shared::build_version(bi));
let allowed_origins = AllowedOrigins::all();
let cors = rocket_cors::CorsOptions {
allowed_origins,
@ -195,7 +195,7 @@ async fn main() -> Result<(), Box<dyn Error>> {
let rkt = rocket::build()
.mount(
letterbox_shared::urls::MOUNT_POINT,
shared::urls::MOUNT_POINT,
routes![
original,
show_pretty,

View File

@ -10,7 +10,7 @@ use crate::TransformError;
#[derive(Error, Debug)]
pub enum ServerError {
#[error("notmuch: {0}")]
NotmuchError(#[from] letterbox_notmuch::NotmuchError),
NotmuchError(#[from] notmuch::NotmuchError),
#[error("flatten")]
FlattenError,
#[error("mail parse error: {0}")]

View File

@ -6,8 +6,8 @@ use async_graphql::{
SimpleObject, Union,
};
use cacher::FilesystemCacher;
use letterbox_notmuch::Notmuch;
use log::info;
use notmuch::Notmuch;
use serde::{Deserialize, Serialize};
use sqlx::postgres::PgPool;
use tokio::join;
@ -283,7 +283,7 @@ pub struct QueryRoot;
impl QueryRoot {
async fn version<'ctx>(&self, _ctx: &Context<'ctx>) -> Result<String, Error> {
build_info::build_info!(fn bi);
Ok(letterbox_shared::build_version(bi))
Ok(shared::build_version(bi))
}
#[instrument(skip_all, fields(query=query))]
#[instrument(skip_all, fields(query=query, request_id=request_id()))]

View File

@ -2,10 +2,10 @@ use std::collections::HashMap;
use cacher::FilesystemCacher;
use futures::{stream::FuturesUnordered, StreamExt};
use letterbox_shared::compute_color;
use log::{error, info};
use maplit::hashmap;
use scraper::Selector;
use shared::compute_color;
use sqlx::postgres::PgPool;
use tracing::instrument;
use url::Url;

View File

@ -5,10 +5,10 @@ use std::{
time::Instant,
};
use letterbox_notmuch::Notmuch;
use log::{error, info, warn};
use mailparse::{parse_content_type, parse_mail, MailHeader, MailHeaderMap, ParsedMail};
use memmap::MmapOptions;
use notmuch::Notmuch;
use sqlx::PgPool;
use tracing::instrument;
@ -43,9 +43,7 @@ pub fn is_notmuch_thread_or_id(id: &str) -> bool {
}
// TODO(wathiede): decide good error type
pub fn threadset_to_messages(
thread_set: letterbox_notmuch::ThreadSet,
) -> Result<Vec<Message>, ServerError> {
pub fn threadset_to_messages(thread_set: notmuch::ThreadSet) -> Result<Vec<Message>, ServerError> {
for t in thread_set.0 {
for _tn in t.0 {}
}
@ -192,7 +190,7 @@ pub async fn thread(
.headers
.get_first_value("date")
.and_then(|d| mailparse::dateparse(&d).ok());
let cid_prefix = letterbox_shared::urls::cid_prefix(None, &id);
let cid_prefix = shared::urls::cid_prefix(None, &id);
let base_url = None;
let mut part_addr = Vec::new();
part_addr.push(id.to_string());

View File

@ -1,15 +1,11 @@
[package]
name = "letterbox-shared"
version = "0.1.0"
name = "shared"
version = "0.0.144"
edition = "2021"
description = "Shared module for letterbox"
license = "UNLICENSED"
repository = "https://git.z.xinu.tv/wathiede/letterbox"
publish = ["xinu"]
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
build-info = "0.0.39"
letterbox-notmuch = { version = "0.1.0", registry = "xinu" }
notmuch = { path = "../notmuch" }
serde = { version = "1.0.147", features = ["derive"] }

View File

@ -1,7 +1,7 @@
use std::hash::{DefaultHasher, Hash, Hasher};
use build_info::{BuildInfo, VersionControl};
use letterbox_notmuch::SearchSummary;
use notmuch::SearchSummary;
use serde::{Deserialize, Serialize};
#[derive(Serialize, Deserialize, Debug)]

View File

@ -1,12 +1,13 @@
[package]
version = "0.1.0"
name = "letterbox-web"
version = "0.0.144"
name = "letterbox"
repository = "https://github.com/seed-rs/seed-quickstart"
authors = ["Bill Thiede <git@xinu.tv>"]
description = "App Description"
categories = ["category"]
license = "MIT"
readme = "./README.md"
edition = "2021"
description = "Web frontend for letterbox"
license = "UNLICENSED"
repository = "https://git.z.xinu.tv/wathiede/letterbox"
publish = ["xinu"]
[build-dependencies]
build-info-build = "0.0.39"
@ -21,6 +22,8 @@ seed = { version = "0.10.0", features = ["routing"] }
#seed = "0.9.2"
console_log = { version = "0.1.0", registry = "xinu" }
serde = { version = "1.0.147", features = ["derive"] }
notmuch = { path = "../notmuch" }
shared = { path = "../shared" }
itertools = "0.14.0"
serde_json = { version = "1.0.93", features = ["unbounded_depth"] }
chrono = "0.4.31"
@ -34,8 +37,6 @@ wasm-bindgen = "=0.2.100"
uuid = { version = "1.13.1", features = [
"js",
] } # direct dep to set js feature, prevents Rng issues
letterbox-shared = { version = "0.1.0", registry = "xinu" }
letterbox-notmuch = { version = "0.1.0", path = "../notmuch", registry = "xinu" }
[package.metadata.wasm-pack.profile.release]
wasm-opt = ['-Os']

View File

@ -27,7 +27,7 @@ pub fn unread_query() -> &'static str {
// `init` describes what should happen when your app started.
pub fn init(url: Url, orders: &mut impl Orders<Msg>) -> Model {
let version = letterbox_shared::build_version(bi);
let version = shared::build_version(bi);
info!("Build Info: {}", version);
if url.hash().is_none() {
orders.request_url(urls::search(unread_query(), 0));

View File

@ -3,10 +3,10 @@ use std::collections::HashSet;
use chrono::{DateTime, Datelike, Duration, Local, Utc};
use human_format::{Formatter, Scales};
use itertools::Itertools;
use letterbox_shared::compute_color;
use log::{debug, error, info};
use seed::{prelude::*, *};
use seed_hooks::{state_access::CloneState, topo, use_state};
use shared::compute_color;
use web_sys::HtmlElement;
use crate::{
@ -87,7 +87,6 @@ pub fn view(model: &Model) -> Node<Msg> {
};
div![
C![
"relative",
"flex",
"flex-wrap-reverse",
"bg-black",
@ -95,17 +94,14 @@ pub fn view(model: &Model) -> Node<Msg> {
"lg:flex-nowrap",
"w-full"
],
reading_progress(model.read_completion_ratio),
div![
C!["w-full", "lg:w-48", "flex-none", "flex", "flex-col"],
tags(model),
versions(&model.versions)
],
reading_progress(model.read_completion_ratio),
div![
// TODO: This "overflow-hidden" is a hack because I can't figure out
// how to prevent the search input box on mobile for growing it's
// parent wider
C!["flex-auto", "flex", "flex-col", "overflow-hidden"],
C!["flex-auto", "flex", "flex-col"],
view_header(&model.query, &model.refreshing_state, true),
content,
view_header(&model.query, &model.refreshing_state, false),
@ -697,12 +693,7 @@ fn render_attachements(
let default = "UNKNOWN_FILE".to_string();
let filename = a.filename.as_ref().unwrap_or(&default);
let host = seed::window().location().host().expect("couldn't get host");
let url = letterbox_shared::urls::download_attachment(
Some(&host),
&a.id,
&a.idx,
filename,
);
let url = shared::urls::download_attachment(Some(&host), &a.id, &a.idx, filename);
let mut fmtr = Formatter::new();
fmtr.with_separator(" ");
fmtr.with_scales(Scales::Binary());
@ -880,7 +871,7 @@ fn view_header(
};
let query = Url::decode_uri_component(query).unwrap_or("".to_string());
nav![
C!["flex", "px-4", "pt-4", "overflow-hidden"],
C!["flex", "px-4", "pt-4"],
a![
C![IF![is_error => "bg-red-500"], "rounded-r-none"],
C![&tw_classes::BUTTON],

View File

@ -56,14 +56,7 @@ html {
background-color: initial !important;
}
.news-post.site-nautilus .article-ad,
.news-post.site-nautilus .primis-ad {
.news-post .site-nautilus .article-ad,
.news-post .site-nautilus .primis-ad {
display: none !important;
}
.news-post.site-slashdot .story-byline {
display: block !important;
height: initial !important;
overflow: auto !important;
position: static !important;
}