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 sqlx::postgres::PgPool;
|
||||||
use tokio::{net::TcpListener, sync::Mutex};
|
use tokio::{net::TcpListener, sync::Mutex};
|
||||||
use tower_http::trace::{DefaultMakeSpan, TraceLayer};
|
use tower_http::trace::{DefaultMakeSpan, TraceLayer};
|
||||||
use tracing::info;
|
use tracing::{info, warn};
|
||||||
|
|
||||||
// Make our own error that wraps `anyhow::Error`.
|
// Make our own error that wraps `anyhow::Error`.
|
||||||
struct AppError(letterbox_server::ServerError);
|
struct AppError(letterbox_server::ServerError);
|
||||||
@ -142,6 +142,25 @@ async fn view_cid(
|
|||||||
Ok(inline_attachment_response(attachment))
|
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 {
|
async fn graphiql() -> impl IntoResponse {
|
||||||
response::Html(
|
response::Html(
|
||||||
GraphiQLSource::build()
|
GraphiQLSource::build()
|
||||||
@ -260,6 +279,7 @@ async fn main() -> Result<(), Box<dyn Error>> {
|
|||||||
get(download_attachment),
|
get(download_attachment),
|
||||||
)
|
)
|
||||||
.route("/view/attachment/{id}/{idx}/{*rest}", get(view_attachment))
|
.route("/view/attachment/{id}/{idx}/{*rest}", get(view_attachment))
|
||||||
|
.route("/original/{id}", get(view_original))
|
||||||
.route("/cid/{id}/{cid}", get(view_cid))
|
.route("/cid/{id}/{cid}", get(view_cid))
|
||||||
.route("/ws", any(start_ws))
|
.route("/ws", any(start_ws))
|
||||||
.route_service("/graphql/ws", GraphQLSubscription::new(schema.clone()))
|
.route_service("/graphql/ws", GraphQLSubscription::new(schema.clone()))
|
||||||
|
|||||||
@ -20,6 +20,13 @@ pub enum WebsocketMessage {
|
|||||||
|
|
||||||
pub mod urls {
|
pub mod urls {
|
||||||
pub const MOUNT_POINT: &'static str = "/api";
|
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 {
|
pub fn cid_prefix(host: Option<&str>, cid: &str) -> String {
|
||||||
if let Some(host) = host {
|
if let Some(host) = host {
|
||||||
format!("//{host}/api/cid/{cid}/")
|
format!("//{host}/api/cid/{cid}/")
|
||||||
|
|||||||
@ -694,6 +694,8 @@ fn render_open_header(msg: &ShowThreadQueryThreadOnEmailThreadMessages) -> Node<
|
|||||||
.collect();
|
.collect();
|
||||||
let show_x_original_to = !*to_xinu.borrow() && msg.x_original_to.is_some();
|
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 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![
|
div![
|
||||||
C!["flex", "p-4", "bg-neutral-800"],
|
C!["flex", "p-4", "bg-neutral-800"],
|
||||||
div![avatar],
|
div![avatar],
|
||||||
@ -775,20 +777,33 @@ fn render_open_header(msg: &ShowThreadQueryThreadOnEmailThreadMessages) -> Node<
|
|||||||
C!["text-right"],
|
C!["text-right"],
|
||||||
msg.timestamp
|
msg.timestamp
|
||||||
.map(|ts| div![C!["text-xs", "text-nowrap"], human_age(ts)]),
|
.map(|ts| div![C!["text-xs", "text-nowrap"], human_age(ts)]),
|
||||||
i![C![
|
div![
|
||||||
"mx-4",
|
C!["p-2"],
|
||||||
"read-status",
|
i![C![
|
||||||
"far",
|
"mx-4",
|
||||||
if is_unread {
|
"read-status",
|
||||||
"fa-envelope"
|
"far",
|
||||||
} else {
|
if is_unread {
|
||||||
"fa-envelope-open"
|
"fa-envelope"
|
||||||
},
|
} else {
|
||||||
]],
|
"fa-envelope-open"
|
||||||
ev(Ev::Click, move |e| {
|
},
|
||||||
e.stop_propagation();
|
]],
|
||||||
Msg::SetUnread(id, !is_unread)
|
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