Add view original functionality

This commit is contained in:
Bill Thiede 2025-04-19 12:33:11 -07:00
parent 122e949072
commit 7d9376d607
3 changed files with 57 additions and 15 deletions

View File

@ -29,7 +29,7 @@ use serde::Deserialize;
use sqlx::postgres::PgPool;
use tokio::{net::TcpListener, sync::Mutex};
use tower_http::trace::{DefaultMakeSpan, TraceLayer};
use tracing::info;
use tracing::{info, warn};
// Make our own error that wraps `anyhow::Error`.
struct AppError(letterbox_server::ServerError);
@ -142,6 +142,25 @@ async fn view_cid(
Ok(inline_attachment_response(attachment))
}
async fn view_original(
State(AppState { nm, .. }): State<AppState>,
extract::Path(id): extract::Path<String>,
) -> Result<impl IntoResponse, AppError> {
info!("view_original {id}");
let mid = if id.starts_with("id:") {
id.to_string()
} else {
format!("id:{}", id)
};
let files = nm.files(&mid)?;
let Some(path) = files.first() else {
warn!("failed to find files for message {mid}");
return Ok((StatusCode::NOT_FOUND, mid).into_response());
};
let str = std::fs::read_to_string(&path)?;
Ok(str.into_response())
}
async fn graphiql() -> impl IntoResponse {
response::Html(
GraphiQLSource::build()
@ -260,6 +279,7 @@ async fn main() -> Result<(), Box<dyn Error>> {
get(download_attachment),
)
.route("/view/attachment/{id}/{idx}/{*rest}", get(view_attachment))
.route("/original/{id}", get(view_original))
.route("/cid/{id}/{cid}", get(view_cid))
.route("/ws", any(start_ws))
.route_service("/graphql/ws", GraphQLSubscription::new(schema.clone()))

View File

@ -20,6 +20,13 @@ pub enum WebsocketMessage {
pub mod urls {
pub const MOUNT_POINT: &'static str = "/api";
pub fn view_original(host: Option<&str>, id: &str) -> String {
if let Some(host) = host {
format!("//{host}/api/original/{id}")
} else {
format!("/api/original/{id}")
}
}
pub fn cid_prefix(host: Option<&str>, cid: &str) -> String {
if let Some(host) = host {
format!("//{host}/api/cid/{cid}/")

View File

@ -694,6 +694,8 @@ fn render_open_header(msg: &ShowThreadQueryThreadOnEmailThreadMessages) -> Node<
.collect();
let show_x_original_to = !*to_xinu.borrow() && msg.x_original_to.is_some();
let show_delivered_to = !*to_xinu.borrow() && !show_x_original_to && msg.delivered_to.is_some();
let host = seed::window().location().host().expect("couldn't get host");
let href = letterbox_shared::urls::view_original(Some(&host), &msg.id);
div![
C!["flex", "p-4", "bg-neutral-800"],
div![avatar],
@ -775,20 +777,33 @@ fn render_open_header(msg: &ShowThreadQueryThreadOnEmailThreadMessages) -> Node<
C!["text-right"],
msg.timestamp
.map(|ts| div![C!["text-xs", "text-nowrap"], human_age(ts)]),
i![C![
"mx-4",
"read-status",
"far",
if is_unread {
"fa-envelope"
} else {
"fa-envelope-open"
},
]],
ev(Ev::Click, move |e| {
e.stop_propagation();
Msg::SetUnread(id, !is_unread)
}),
div![
C!["p-2"],
i![C![
"mx-4",
"read-status",
"far",
if is_unread {
"fa-envelope"
} else {
"fa-envelope-open"
},
]],
ev(Ev::Click, move |e| {
e.stop_propagation();
Msg::SetUnread(id, !is_unread)
}),
],
div![
C!["text-xs"],
span![a![
attrs! {
At::Href=>href,
At::Target=>"_blank",
},
"View original"
]]
]
]
]
}