Add image view page, improve opengraph
This commit is contained in:
parent
1a1d280bac
commit
34b6623593
81
src/main.rs
81
src/main.rs
|
@ -96,6 +96,17 @@ impl Config {
|
|||
url.to_string()
|
||||
}
|
||||
|
||||
fn view_url(&self, size: Option<u64>, name: &str) -> String {
|
||||
let mut url = self.domain.clone();
|
||||
if let Some(size) = size {
|
||||
url.set_path(&format!("view/{}/{}", size, name));
|
||||
} else {
|
||||
url.set_path(&format!("view/{}", name));
|
||||
}
|
||||
|
||||
url.to_string()
|
||||
}
|
||||
|
||||
fn thumbnails_url(&self, name: &str) -> String {
|
||||
let mut url = self.domain.clone();
|
||||
url.set_path("/thumbnails");
|
||||
|
@ -158,6 +169,14 @@ impl Images {
|
|||
fn is_ok(&self) -> bool {
|
||||
self.files().is_some()
|
||||
}
|
||||
|
||||
fn message(&self) -> &'static str {
|
||||
if self.is_ok() {
|
||||
"Images Uploaded"
|
||||
} else {
|
||||
"Image Upload Failed"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, serde::Deserialize)]
|
||||
|
@ -179,6 +198,10 @@ impl Image {
|
|||
CONFIG.thumbnails_url(&self.file)
|
||||
}
|
||||
|
||||
fn view(&self, size: Option<u64>) -> String {
|
||||
CONFIG.view_url(size, &self.file)
|
||||
}
|
||||
|
||||
fn thumb(&self, size: u64, filetype: FileType) -> String {
|
||||
CONFIG.thumbnail_url(size, &self.file, filetype)
|
||||
}
|
||||
|
@ -322,6 +345,62 @@ async fn image(
|
|||
Ok(client_res.body(BodyStream::new(res)))
|
||||
}
|
||||
|
||||
async fn view_original(
|
||||
file: web::Path<String>,
|
||||
client: web::Data<Client>,
|
||||
) -> Result<HttpResponse, Error> {
|
||||
let file = file.into_inner();
|
||||
|
||||
let url = CONFIG.upstream_image_url(&file);
|
||||
let res = client.get(url).send().await?;
|
||||
|
||||
if res.status() == StatusCode::NOT_FOUND {
|
||||
return Ok(to_404());
|
||||
}
|
||||
|
||||
let image = Image {
|
||||
file,
|
||||
delete_token: String::new(),
|
||||
};
|
||||
|
||||
let mut cursor = Cursor::new(vec![]);
|
||||
self::templates::view(&mut cursor, image, None)?;
|
||||
|
||||
Ok(HttpResponse::Ok()
|
||||
.content_type(mime::TEXT_HTML.essence_str())
|
||||
.body(cursor.into_inner()))
|
||||
}
|
||||
|
||||
async fn view(
|
||||
parts: web::Path<(u64, String)>,
|
||||
client: web::Data<Client>,
|
||||
) -> Result<HttpResponse, Error> {
|
||||
let (size, file) = parts.into_inner();
|
||||
|
||||
if !valid_thumbnail_size(size) {
|
||||
return Ok(to_404());
|
||||
}
|
||||
|
||||
let url = CONFIG.upstream_image_url(&file);
|
||||
let res = client.get(url).send().await?;
|
||||
|
||||
if res.status() == StatusCode::NOT_FOUND {
|
||||
return Ok(to_404());
|
||||
}
|
||||
|
||||
let image = Image {
|
||||
file,
|
||||
delete_token: String::new(),
|
||||
};
|
||||
|
||||
let mut cursor = Cursor::new(vec![]);
|
||||
self::templates::view(&mut cursor, image, Some(size))?;
|
||||
|
||||
Ok(HttpResponse::Ok()
|
||||
.content_type(mime::TEXT_HTML.essence_str())
|
||||
.body(cursor.into_inner()))
|
||||
}
|
||||
|
||||
async fn thumbnail(
|
||||
parts: web::Path<(u64, FileType, String)>,
|
||||
req: HttpRequest,
|
||||
|
@ -460,6 +539,8 @@ async fn main() -> Result<(), anyhow::Error> {
|
|||
.service(web::resource("/upload").route(web::post().to(upload)))
|
||||
.service(web::resource("/image/{filename}").route(web::get().to(full_res)))
|
||||
.service(web::resource("thumbnails").route(web::get().to(thumbs)))
|
||||
.service(web::resource("/view/{size}/{filename}").route(web::get().to(view)))
|
||||
.service(web::resource("/view/{filename}").route(web::get().to(view_original)))
|
||||
.service(
|
||||
web::resource("/thumb/{size}/{filetype}/{filename}")
|
||||
.route(web::get().to(thumbnail)),
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
@(image: &Image)
|
||||
|
||||
@:layout_html({
|
||||
@:layout_html("Confirm Delete", Some(&format!("Delete {} from pict-rs", image.filename())), {
|
||||
<title>Confirm Delete</title>
|
||||
<link rel="stylesheet" href="@crate::statics(&images_css.name)" type="text/css" />
|
||||
}, {
|
||||
|
|
|
@ -2,9 +2,7 @@
|
|||
|
||||
@(filename: &str)
|
||||
|
||||
@:layout_html({
|
||||
<title>Deleted @filename</title>
|
||||
}, {
|
||||
@:layout_html(&format!("Deleted {}", filename), None, {}, {
|
||||
<section>
|
||||
<article>
|
||||
<h3>Deleted @filename</h3>
|
||||
|
|
|
@ -2,9 +2,7 @@
|
|||
|
||||
@(msg: &str)
|
||||
|
||||
@:layout_html({
|
||||
<title>Error</title>
|
||||
}, {
|
||||
@:layout_html("Error", None, {}, {
|
||||
<section>
|
||||
<article>
|
||||
<h3>There was an error processing your request</h3>
|
||||
|
|
|
@ -3,12 +3,7 @@
|
|||
|
||||
@(images: Images)
|
||||
|
||||
@:layout_html({
|
||||
@if images.is_ok() {
|
||||
<title>Images Uploaded</title>
|
||||
} else {
|
||||
<title>Image Upload Failed</title>
|
||||
}
|
||||
@:layout_html(images.message(), None, {
|
||||
<link rel="stylesheet" href="@crate::statics(&images_css.name)" type="text/css" />
|
||||
}, {
|
||||
<section>
|
||||
|
@ -32,11 +27,11 @@
|
|||
<p>
|
||||
Link:<br />
|
||||
<a
|
||||
href="@image.link()"
|
||||
href="@image.view(None)"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
@image.link()
|
||||
@image.view(None)
|
||||
</a>
|
||||
</p>
|
||||
<p>
|
||||
|
|
|
@ -2,8 +2,7 @@
|
|||
|
||||
@(endpoint: &str, name: &str)
|
||||
|
||||
@:layout_html({
|
||||
<title>Upload images</title>
|
||||
@:layout_html("Upload Images", None, {
|
||||
<link rel="stylesheet" href="@crate::statics(&form_css.name)" type="text/css" />
|
||||
<script src="@crate::statics(&form_js.name)" type="text/javascript"></script>
|
||||
}, {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
@use super::statics::{layout_css, favicon_ico};
|
||||
|
||||
@(head: Content, body: Content)
|
||||
@(title: &str, description: Option<&str>, head: Content, body: Content)
|
||||
|
||||
<!DOCTYPE html>
|
||||
|
||||
|
@ -8,9 +8,14 @@
|
|||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<title>@title</title>
|
||||
<link rel="stylesheet" href="@crate::statics(&layout_css.name)" type="text/css" />
|
||||
<meta property="og:title" content="A simple image host" />
|
||||
<meta property="og:description" content="Upload and share image files" />
|
||||
<meta property="og:title" content="@title" />
|
||||
@if let Some(description) = description {
|
||||
<meta property="og:description" content="@description" />
|
||||
} else {
|
||||
<meta property="og:description" content="Upload and share image files" />
|
||||
}
|
||||
<meta property="og:type" content="website" />
|
||||
<link rel="shortcut icon" type="image/png" href="@crate::statics(&favicon_ico.name)">
|
||||
@:head()
|
||||
|
|
|
@ -2,8 +2,7 @@
|
|||
|
||||
@()
|
||||
|
||||
@:layout_html({
|
||||
<title>Not Found</title>
|
||||
@:layout_html("Not Found", None, {
|
||||
<link rel="stylesheet" href="@crate::statics(¬_found_css.name)" type="text/css" />
|
||||
}, {
|
||||
<section>
|
||||
|
|
|
@ -3,8 +3,10 @@
|
|||
|
||||
@(image: Image, sizes: &[u64])
|
||||
|
||||
@:layout_html({
|
||||
<title>Thumbnails</title>
|
||||
@:layout_html("Thumbnails", Some(&format!("Thumbnails for {}", image.filename())), {
|
||||
<meta property="og:image" content="@image.link()" />
|
||||
<meta property="og:url" content="@image.link()" />
|
||||
<meta property="og:image:alt" content="Image: @image.filename()" />
|
||||
<link rel="stylesheet" href="@crate::statics(&images_css.name)" type="text/css" />
|
||||
}, {
|
||||
<section>
|
||||
|
@ -14,7 +16,7 @@
|
|||
<ul>
|
||||
<li>
|
||||
<article>
|
||||
<p>Original File:<br /><a href="@image.link()">@image.link()</a></p>
|
||||
<p>Original File:<br /><a href="@image.view(None)">@image.view(None)</a></p>
|
||||
</article>
|
||||
</li>
|
||||
@for size in sizes {
|
||||
|
@ -27,11 +29,11 @@
|
|||
<p>@size x @size</p>
|
||||
<p>
|
||||
<a
|
||||
href="@image.thumb(*size, FileType::Jpg)"
|
||||
href="@image.view(Some(*size))"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
@image.thumb(*size, FileType::Jpg)
|
||||
@image.view(Some(*size))
|
||||
</a>
|
||||
</p>
|
||||
</article>
|
||||
|
|
35
templates/view.rs.html
Normal file
35
templates/view.rs.html
Normal file
|
@ -0,0 +1,35 @@
|
|||
@use super::{layout_html, return_home_html, statics::images_css};
|
||||
@use crate::{Image, FileType};
|
||||
|
||||
@(image: Image, size: Option<u64>)
|
||||
|
||||
@:layout_html(&format!("Image: {}", image.filename()), Some("An image hosted on pict-rs"), {
|
||||
<link rel="stylesheet" href="@crate::statics(&images_css.name)" type="text/css" />
|
||||
@if let Some(size) = size {
|
||||
<meta property="og:image" content="@image.thumb(size, FileType::Jpg)" />
|
||||
<meta property="og:url" content="@image.view(Some(size))" />
|
||||
<meta property="og:image:type" content="image/jpg" />
|
||||
} else {
|
||||
<meta property="og:image" content="@image.link()" />
|
||||
<meta property="og:url" content="@image.view(None)" />
|
||||
}
|
||||
<meta property="og:image:alt" content="Image: @image.filename()" />
|
||||
}, {
|
||||
<section>
|
||||
<article>
|
||||
<div>
|
||||
@if let Some(size) = size {
|
||||
<picture>
|
||||
<source type="image/webp" srcset="@image.thumb(size, FileType::Webp)" />
|
||||
<img src="@image.thumb(size, FileType::Jpg)" alt="@image.filename()" title="@image.filename()" />
|
||||
</picture>
|
||||
<p><a href="@image.thumb(size, FileType::Jpg)">Direct Link</a></p>
|
||||
} else {
|
||||
<img src="@image.link()" alt="@image.filename()" title="@image.filename()" />
|
||||
<p><a href="@image.link()">Direct Link</a></p>
|
||||
}
|
||||
</div>
|
||||
</article>
|
||||
@:return_home_html()
|
||||
</section>
|
||||
})
|
Loading…
Reference in a new issue