Compare commits
10 Commits
c7740811bf
...
ee9b6be95e
| Author | SHA1 | Date | |
|---|---|---|---|
| ee9b6be95e | |||
| 38c553d385 | |||
| 1b073665a7 | |||
| 2076596f50 | |||
| d1beaded09 | |||
| 2562bdfedf | |||
| 86c6face7d | |||
| 4a7ff8bf7b | |||
| 8c280d3616 | |||
| eb4d4164ef |
7077
Cargo.lock
generated
7077
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
@ -1,7 +1,8 @@
|
|||||||
[workspace]
|
[workspace]
|
||||||
resolver = "2"
|
resolver = "2"
|
||||||
default-members = ["server"]
|
#default-members = ["server"]
|
||||||
members = ["web", "server", "notmuch", "procmail2notmuch", "shared"]
|
members = ["notmuch", "procmail2notmuch", "shared"]
|
||||||
|
#members = ["web", "server", "notmuch", "procmail2notmuch", "shared"]
|
||||||
|
|
||||||
[profile.dev]
|
[profile.dev]
|
||||||
opt-level = 1
|
opt-level = 1
|
||||||
|
|||||||
@ -1,9 +1,13 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "notmuch"
|
name = "letterbox-notmuch"
|
||||||
version = "0.0.144"
|
version = "0.1.0"
|
||||||
edition = "2021"
|
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]
|
[dependencies]
|
||||||
log = "0.4.14"
|
log = "0.4.14"
|
||||||
|
|||||||
@ -4,7 +4,7 @@ use std::{
|
|||||||
time::Instant,
|
time::Instant,
|
||||||
};
|
};
|
||||||
|
|
||||||
use notmuch::Notmuch;
|
use letterbox_notmuch::Notmuch;
|
||||||
use rayon::iter::{ParallelBridge, ParallelIterator};
|
use rayon::iter::{ParallelBridge, ParallelIterator};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|||||||
@ -1,7 +1,11 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "procmail2notmuch"
|
name = "letterbox-procmail2notmuch"
|
||||||
version = "0.0.144"
|
version = "0.1.0"
|
||||||
edition = "2021"
|
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
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
|
|||||||
@ -1,8 +1,12 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "letterbox-server"
|
name = "letterbox-server"
|
||||||
version = "0.0.144"
|
version = "0.1.0"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
default-run = "letterbox-server"
|
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
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
@ -25,7 +29,6 @@ lol_html = "2.0.0"
|
|||||||
mailparse = "0.16.0"
|
mailparse = "0.16.0"
|
||||||
maplit = "1.0.2"
|
maplit = "1.0.2"
|
||||||
memmap = "0.7.0"
|
memmap = "0.7.0"
|
||||||
notmuch = { path = "../notmuch" }
|
|
||||||
opentelemetry = "0.28.0"
|
opentelemetry = "0.28.0"
|
||||||
regex = "1.11.1"
|
regex = "1.11.1"
|
||||||
reqwest = { version = "0.12.7", features = ["blocking"] }
|
reqwest = { version = "0.12.7", features = ["blocking"] }
|
||||||
@ -34,7 +37,6 @@ rocket_cors = "0.6.0"
|
|||||||
scraper = "0.22.0"
|
scraper = "0.22.0"
|
||||||
serde = { version = "1.0.147", features = ["derive"] }
|
serde = { version = "1.0.147", features = ["derive"] }
|
||||||
serde_json = "1.0.87"
|
serde_json = "1.0.87"
|
||||||
shared = { path = "../shared" }
|
|
||||||
sqlx = { version = "0.8.2", features = ["postgres", "runtime-tokio", "time"] }
|
sqlx = { version = "0.8.2", features = ["postgres", "runtime-tokio", "time"] }
|
||||||
tantivy = { version = "0.22.0", optional = true }
|
tantivy = { version = "0.22.0", optional = true }
|
||||||
thiserror = "2.0.0"
|
thiserror = "2.0.0"
|
||||||
@ -45,6 +47,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.2.0", registry = "xinu" }
|
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-dependencies]
|
||||||
build-info-build = "0.0.39"
|
build-info-build = "0.0.39"
|
||||||
|
|||||||
13
server/sql/too-long-for-search.sql
Normal file
13
server/sql/too-long-for-search.sql
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
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;
|
||||||
21
server/src/bin/inline_html.rs
Normal file
21
server/src/bin/inline_html.rs
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
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(())
|
||||||
|
}
|
||||||
@ -8,6 +8,7 @@ use std::{error::Error, io::Cursor, str::FromStr};
|
|||||||
use async_graphql::{extensions, http::GraphiQLSource, EmptySubscription, Schema};
|
use async_graphql::{extensions, http::GraphiQLSource, EmptySubscription, Schema};
|
||||||
use async_graphql_rocket::{GraphQLQuery, GraphQLRequest, GraphQLResponse};
|
use async_graphql_rocket::{GraphQLQuery, GraphQLRequest, GraphQLResponse};
|
||||||
use cacher::FilesystemCacher;
|
use cacher::FilesystemCacher;
|
||||||
|
use letterbox_notmuch::{Notmuch, NotmuchError, ThreadSet};
|
||||||
#[cfg(feature = "tantivy")]
|
#[cfg(feature = "tantivy")]
|
||||||
use letterbox_server::tantivy::TantivyConnection;
|
use letterbox_server::tantivy::TantivyConnection;
|
||||||
use letterbox_server::{
|
use letterbox_server::{
|
||||||
@ -16,7 +17,6 @@ use letterbox_server::{
|
|||||||
graphql::{Attachment, GraphqlSchema, Mutation, QueryRoot},
|
graphql::{Attachment, GraphqlSchema, Mutation, QueryRoot},
|
||||||
nm::{attachment_bytes, cid_attachment_bytes},
|
nm::{attachment_bytes, cid_attachment_bytes},
|
||||||
};
|
};
|
||||||
use notmuch::{Notmuch, NotmuchError, ThreadSet};
|
|
||||||
use rocket::{
|
use rocket::{
|
||||||
fairing::AdHoc,
|
fairing::AdHoc,
|
||||||
http::{ContentType, Header},
|
http::{ContentType, Header},
|
||||||
@ -179,7 +179,7 @@ async fn graphql_request(
|
|||||||
async fn main() -> Result<(), Box<dyn Error>> {
|
async fn main() -> Result<(), Box<dyn Error>> {
|
||||||
let _guard = xtracing::init(env!("CARGO_BIN_NAME"))?;
|
let _guard = xtracing::init(env!("CARGO_BIN_NAME"))?;
|
||||||
build_info::build_info!(fn bi);
|
build_info::build_info!(fn bi);
|
||||||
info!("Build Info: {}", shared::build_version(bi));
|
info!("Build Info: {}", letterbox_shared::build_version(bi));
|
||||||
let allowed_origins = AllowedOrigins::all();
|
let allowed_origins = AllowedOrigins::all();
|
||||||
let cors = rocket_cors::CorsOptions {
|
let cors = rocket_cors::CorsOptions {
|
||||||
allowed_origins,
|
allowed_origins,
|
||||||
@ -195,7 +195,7 @@ async fn main() -> Result<(), Box<dyn Error>> {
|
|||||||
|
|
||||||
let rkt = rocket::build()
|
let rkt = rocket::build()
|
||||||
.mount(
|
.mount(
|
||||||
shared::urls::MOUNT_POINT,
|
letterbox_shared::urls::MOUNT_POINT,
|
||||||
routes![
|
routes![
|
||||||
original,
|
original,
|
||||||
show_pretty,
|
show_pretty,
|
||||||
|
|||||||
@ -10,7 +10,7 @@ use crate::TransformError;
|
|||||||
#[derive(Error, Debug)]
|
#[derive(Error, Debug)]
|
||||||
pub enum ServerError {
|
pub enum ServerError {
|
||||||
#[error("notmuch: {0}")]
|
#[error("notmuch: {0}")]
|
||||||
NotmuchError(#[from] notmuch::NotmuchError),
|
NotmuchError(#[from] letterbox_notmuch::NotmuchError),
|
||||||
#[error("flatten")]
|
#[error("flatten")]
|
||||||
FlattenError,
|
FlattenError,
|
||||||
#[error("mail parse error: {0}")]
|
#[error("mail parse error: {0}")]
|
||||||
|
|||||||
@ -6,8 +6,8 @@ use async_graphql::{
|
|||||||
SimpleObject, Union,
|
SimpleObject, Union,
|
||||||
};
|
};
|
||||||
use cacher::FilesystemCacher;
|
use cacher::FilesystemCacher;
|
||||||
|
use letterbox_notmuch::Notmuch;
|
||||||
use log::info;
|
use log::info;
|
||||||
use notmuch::Notmuch;
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use sqlx::postgres::PgPool;
|
use sqlx::postgres::PgPool;
|
||||||
use tokio::join;
|
use tokio::join;
|
||||||
@ -283,7 +283,7 @@ pub struct QueryRoot;
|
|||||||
impl QueryRoot {
|
impl QueryRoot {
|
||||||
async fn version<'ctx>(&self, _ctx: &Context<'ctx>) -> Result<String, Error> {
|
async fn version<'ctx>(&self, _ctx: &Context<'ctx>) -> Result<String, Error> {
|
||||||
build_info::build_info!(fn bi);
|
build_info::build_info!(fn bi);
|
||||||
Ok(shared::build_version(bi))
|
Ok(letterbox_shared::build_version(bi))
|
||||||
}
|
}
|
||||||
#[instrument(skip_all, fields(query=query))]
|
#[instrument(skip_all, fields(query=query))]
|
||||||
#[instrument(skip_all, fields(query=query, request_id=request_id()))]
|
#[instrument(skip_all, fields(query=query, request_id=request_id()))]
|
||||||
|
|||||||
@ -2,10 +2,10 @@ use std::collections::HashMap;
|
|||||||
|
|
||||||
use cacher::FilesystemCacher;
|
use cacher::FilesystemCacher;
|
||||||
use futures::{stream::FuturesUnordered, StreamExt};
|
use futures::{stream::FuturesUnordered, StreamExt};
|
||||||
|
use letterbox_shared::compute_color;
|
||||||
use log::{error, info};
|
use log::{error, info};
|
||||||
use maplit::hashmap;
|
use maplit::hashmap;
|
||||||
use scraper::Selector;
|
use scraper::Selector;
|
||||||
use shared::compute_color;
|
|
||||||
use sqlx::postgres::PgPool;
|
use sqlx::postgres::PgPool;
|
||||||
use tracing::instrument;
|
use tracing::instrument;
|
||||||
use url::Url;
|
use url::Url;
|
||||||
|
|||||||
@ -5,10 +5,10 @@ use std::{
|
|||||||
time::Instant,
|
time::Instant,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use letterbox_notmuch::Notmuch;
|
||||||
use log::{error, info, warn};
|
use log::{error, info, warn};
|
||||||
use mailparse::{parse_content_type, parse_mail, MailHeader, MailHeaderMap, ParsedMail};
|
use mailparse::{parse_content_type, parse_mail, MailHeader, MailHeaderMap, ParsedMail};
|
||||||
use memmap::MmapOptions;
|
use memmap::MmapOptions;
|
||||||
use notmuch::Notmuch;
|
|
||||||
use sqlx::PgPool;
|
use sqlx::PgPool;
|
||||||
use tracing::instrument;
|
use tracing::instrument;
|
||||||
|
|
||||||
@ -43,7 +43,9 @@ pub fn is_notmuch_thread_or_id(id: &str) -> bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TODO(wathiede): decide good error type
|
// TODO(wathiede): decide good error type
|
||||||
pub fn threadset_to_messages(thread_set: notmuch::ThreadSet) -> Result<Vec<Message>, ServerError> {
|
pub fn threadset_to_messages(
|
||||||
|
thread_set: letterbox_notmuch::ThreadSet,
|
||||||
|
) -> Result<Vec<Message>, ServerError> {
|
||||||
for t in thread_set.0 {
|
for t in thread_set.0 {
|
||||||
for _tn in t.0 {}
|
for _tn in t.0 {}
|
||||||
}
|
}
|
||||||
@ -190,7 +192,7 @@ pub async fn thread(
|
|||||||
.headers
|
.headers
|
||||||
.get_first_value("date")
|
.get_first_value("date")
|
||||||
.and_then(|d| mailparse::dateparse(&d).ok());
|
.and_then(|d| mailparse::dateparse(&d).ok());
|
||||||
let cid_prefix = shared::urls::cid_prefix(None, &id);
|
let cid_prefix = letterbox_shared::urls::cid_prefix(None, &id);
|
||||||
let base_url = None;
|
let base_url = None;
|
||||||
let mut part_addr = Vec::new();
|
let mut part_addr = Vec::new();
|
||||||
part_addr.push(id.to_string());
|
part_addr.push(id.to_string());
|
||||||
|
|||||||
@ -1,11 +1,15 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "shared"
|
name = "letterbox-shared"
|
||||||
version = "0.0.144"
|
version = "0.1.0"
|
||||||
edition = "2021"
|
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
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
build-info = "0.0.39"
|
build-info = "0.0.39"
|
||||||
notmuch = { path = "../notmuch" }
|
letterbox-notmuch = { version = "0.1.0", registry = "xinu" }
|
||||||
serde = { version = "1.0.147", features = ["derive"] }
|
serde = { version = "1.0.147", features = ["derive"] }
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
use std::hash::{DefaultHasher, Hash, Hasher};
|
use std::hash::{DefaultHasher, Hash, Hasher};
|
||||||
|
|
||||||
use build_info::{BuildInfo, VersionControl};
|
use build_info::{BuildInfo, VersionControl};
|
||||||
use notmuch::SearchSummary;
|
use letterbox_notmuch::SearchSummary;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug)]
|
#[derive(Serialize, Deserialize, Debug)]
|
||||||
|
|||||||
@ -1,13 +1,12 @@
|
|||||||
[package]
|
[package]
|
||||||
version = "0.0.144"
|
version = "0.1.0"
|
||||||
name = "letterbox"
|
name = "letterbox-web"
|
||||||
repository = "https://github.com/seed-rs/seed-quickstart"
|
|
||||||
authors = ["Bill Thiede <git@xinu.tv>"]
|
authors = ["Bill Thiede <git@xinu.tv>"]
|
||||||
description = "App Description"
|
|
||||||
categories = ["category"]
|
|
||||||
license = "MIT"
|
|
||||||
readme = "./README.md"
|
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
description = "Web frontend for letterbox"
|
||||||
|
license = "UNLICENSED"
|
||||||
|
repository = "https://git.z.xinu.tv/wathiede/letterbox"
|
||||||
|
publish = ["xinu"]
|
||||||
|
|
||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
build-info-build = "0.0.39"
|
build-info-build = "0.0.39"
|
||||||
@ -22,8 +21,6 @@ seed = { version = "0.10.0", features = ["routing"] }
|
|||||||
#seed = "0.9.2"
|
#seed = "0.9.2"
|
||||||
console_log = { version = "0.1.0", registry = "xinu" }
|
console_log = { version = "0.1.0", registry = "xinu" }
|
||||||
serde = { version = "1.0.147", features = ["derive"] }
|
serde = { version = "1.0.147", features = ["derive"] }
|
||||||
notmuch = { path = "../notmuch" }
|
|
||||||
shared = { path = "../shared" }
|
|
||||||
itertools = "0.14.0"
|
itertools = "0.14.0"
|
||||||
serde_json = { version = "1.0.93", features = ["unbounded_depth"] }
|
serde_json = { version = "1.0.93", features = ["unbounded_depth"] }
|
||||||
chrono = "0.4.31"
|
chrono = "0.4.31"
|
||||||
@ -37,6 +34,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.1.0", registry = "xinu" }
|
||||||
|
letterbox-notmuch = { version = "0.1.0", path = "../notmuch", registry = "xinu" }
|
||||||
|
|
||||||
[package.metadata.wasm-pack.profile.release]
|
[package.metadata.wasm-pack.profile.release]
|
||||||
wasm-opt = ['-Os']
|
wasm-opt = ['-Os']
|
||||||
|
|||||||
@ -27,7 +27,7 @@ pub fn unread_query() -> &'static str {
|
|||||||
|
|
||||||
// `init` describes what should happen when your app started.
|
// `init` describes what should happen when your app started.
|
||||||
pub fn init(url: Url, orders: &mut impl Orders<Msg>) -> Model {
|
pub fn init(url: Url, orders: &mut impl Orders<Msg>) -> Model {
|
||||||
let version = shared::build_version(bi);
|
let version = letterbox_shared::build_version(bi);
|
||||||
info!("Build Info: {}", version);
|
info!("Build Info: {}", version);
|
||||||
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));
|
||||||
|
|||||||
@ -3,10 +3,10 @@ use std::collections::HashSet;
|
|||||||
use chrono::{DateTime, Datelike, Duration, Local, Utc};
|
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 log::{debug, error, info};
|
use log::{debug, error, info};
|
||||||
use seed::{prelude::*, *};
|
use seed::{prelude::*, *};
|
||||||
use seed_hooks::{state_access::CloneState, topo, use_state};
|
use seed_hooks::{state_access::CloneState, topo, use_state};
|
||||||
use shared::compute_color;
|
|
||||||
use web_sys::HtmlElement;
|
use web_sys::HtmlElement;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
@ -87,6 +87,7 @@ pub fn view(model: &Model) -> Node<Msg> {
|
|||||||
};
|
};
|
||||||
div![
|
div![
|
||||||
C![
|
C![
|
||||||
|
"relative",
|
||||||
"flex",
|
"flex",
|
||||||
"flex-wrap-reverse",
|
"flex-wrap-reverse",
|
||||||
"bg-black",
|
"bg-black",
|
||||||
@ -94,14 +95,17 @@ pub fn view(model: &Model) -> Node<Msg> {
|
|||||||
"lg:flex-nowrap",
|
"lg:flex-nowrap",
|
||||||
"w-full"
|
"w-full"
|
||||||
],
|
],
|
||||||
|
reading_progress(model.read_completion_ratio),
|
||||||
div![
|
div![
|
||||||
C!["w-full", "lg:w-48", "flex-none", "flex", "flex-col"],
|
C!["w-full", "lg:w-48", "flex-none", "flex", "flex-col"],
|
||||||
tags(model),
|
tags(model),
|
||||||
versions(&model.versions)
|
versions(&model.versions)
|
||||||
],
|
],
|
||||||
reading_progress(model.read_completion_ratio),
|
|
||||||
div![
|
div![
|
||||||
C!["flex-auto", "flex", "flex-col"],
|
// 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"],
|
||||||
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),
|
||||||
@ -693,7 +697,12 @@ fn render_attachements(
|
|||||||
let default = "UNKNOWN_FILE".to_string();
|
let default = "UNKNOWN_FILE".to_string();
|
||||||
let filename = a.filename.as_ref().unwrap_or(&default);
|
let filename = a.filename.as_ref().unwrap_or(&default);
|
||||||
let host = seed::window().location().host().expect("couldn't get host");
|
let host = seed::window().location().host().expect("couldn't get host");
|
||||||
let url = shared::urls::download_attachment(Some(&host), &a.id, &a.idx, filename);
|
let url = letterbox_shared::urls::download_attachment(
|
||||||
|
Some(&host),
|
||||||
|
&a.id,
|
||||||
|
&a.idx,
|
||||||
|
filename,
|
||||||
|
);
|
||||||
let mut fmtr = Formatter::new();
|
let mut fmtr = Formatter::new();
|
||||||
fmtr.with_separator(" ");
|
fmtr.with_separator(" ");
|
||||||
fmtr.with_scales(Scales::Binary());
|
fmtr.with_scales(Scales::Binary());
|
||||||
@ -871,7 +880,7 @@ fn view_header(
|
|||||||
};
|
};
|
||||||
let query = Url::decode_uri_component(query).unwrap_or("".to_string());
|
let query = Url::decode_uri_component(query).unwrap_or("".to_string());
|
||||||
nav![
|
nav![
|
||||||
C!["flex", "px-4", "pt-4"],
|
C!["flex", "px-4", "pt-4", "overflow-hidden"],
|
||||||
a![
|
a![
|
||||||
C![IF![is_error => "bg-red-500"], "rounded-r-none"],
|
C![IF![is_error => "bg-red-500"], "rounded-r-none"],
|
||||||
C![&tw_classes::BUTTON],
|
C![&tw_classes::BUTTON],
|
||||||
|
|||||||
@ -60,3 +60,10 @@ html {
|
|||||||
.news-post.site-nautilus .primis-ad {
|
.news-post.site-nautilus .primis-ad {
|
||||||
display: none !important;
|
display: none !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.news-post.site-slashdot .story-byline {
|
||||||
|
display: block !important;
|
||||||
|
height: initial !important;
|
||||||
|
overflow: auto !important;
|
||||||
|
position: static !important;
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user