Add view original functionality
This commit is contained in:
parent
122e949072
commit
7d9376d607
@ -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()))
|
||||
|
||||
@ -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}/")
|
||||
|
||||
@ -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"
|
||||
]]
|
||||
]
|
||||
]
|
||||
]
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user