From c4939e02b80bf857419a257be316b5f87eae3445 Mon Sep 17 00:00:00 2001 From: "Jakob L. Kreuze" Date: Thu, 28 May 2020 19:58:23 -0400 Subject: Implement per-image information and display. --- README.md | 1 + src/database.rs | 19 ++++++++++++++++ src/main.rs | 64 +++++++++++++++++++++++++++++++++++++---------------- templates/image.hbs | 35 +++++++++++++++++++++++++++++ templates/index.hbs | 6 ++--- 5 files changed, 103 insertions(+), 22 deletions(-) create mode 100644 templates/image.hbs diff --git a/README.md b/README.md index 7ec8b92..c18c66f 100644 --- a/README.md +++ b/README.md @@ -81,6 +81,7 @@ Suppose we denote the following shape of JSON object as a `ImageResult`. "id": number, "filename": string, "thumb_filename": string, + "orig_filename": string, "tags": [string, ...], } ``` diff --git a/src/database.rs b/src/database.rs index 055d1ef..54f511f 100644 --- a/src/database.rs +++ b/src/database.rs @@ -128,6 +128,25 @@ impl TagDatabase { .query_row(params![path, file_name], |row| Ok(row.get::<_, i64>(0)))??) } + /// Return the `Image` struct for the image with `id`. + pub fn image_by_id(&self, id: i64) -> Result { + Ok(self + .0 + .prepare( + "SELECT id, blake2, filename, orig_dir + FROM images + WHERE id = ?", + )? + .query_row(params![id], |row| { + Ok(Image { + id: row.get(0)?, + blake2: row.get(1)?, + filename: row.get(2)?, + orig_dir: row.get(3)?, + }) + })?) + } + /// Associate `tag` with the image specified by `image_id`. pub fn tag_image(&self, image_id: i64, tag: &str) -> Result<()> { self.0.execute( diff --git a/src/main.rs b/src/main.rs index d53d0d0..2a5b440 100644 --- a/src/main.rs +++ b/src/main.rs @@ -71,20 +71,25 @@ struct ImageResult { id: i64, filename: String, thumb_filename: String, + orig_filename: String, tags: Vec, } +fn image_store_filename(id: i64, filename: &str) -> String { + if let Some(n) = filename.rfind('.') { + format!("{id}.{ext}", id = id, ext = &filename[n + 1..]) + } else { + id.to_string() + } +} + /// Return the file name of the thumbnail for the image at `filename`. -fn thumb_filename(filename: &str) -> String { - String::from(format!( - "{}_thumb.png", - // Strip extension. - if let Some(n) = filename.rfind('.') { - &filename[..n] - } else { - &filename[..] - } - )) +fn thumb_filename(id: i64, filename: &str) -> String { + if let Some(n) = filename.rfind('.') { + format!("{id}_thumb.{ext}", id = id, ext = &filename[n + 1..]) + } else { + format!("{id}_thumb", id = id) + } } #[get("/posts?&")] @@ -111,16 +116,31 @@ fn get_posts(conn: SiteState, tags: String, last: Option) -> Json")] +fn get_post(conn: SiteState, id: i64) -> Json { + let tb = &conn.inner().lock().unwrap().tb; + let image = tb.image_by_id(id).unwrap(); + + Json(ImageResult { + id: image.id, + filename: image_store_filename(image.id, &image.filename), + thumb_filename: thumb_filename(image.id, &image.filename), + orig_filename: image.filename.clone(), + tags: tb.tags_for_image(image.id).unwrap(), + }) +} + #[post("/posts/", data = "")] -fn put_posts(conn: SiteState, filename: String, data: Data) -> Json<&str> { +fn put_post(conn: SiteState, filename: String, data: Data) -> Json<&str> { let conn = conn.inner().lock().unwrap(); let path = Path::new(&conn.image_dir).join(filename); data.stream_to_file(&path).unwrap(); @@ -181,19 +201,25 @@ fn display_posts(conn: SiteState, tags: String, last: Option) -> Template { Template::render("index", context) } +#[get("/posts/")] +fn display_post(conn: SiteState, id: i64) -> Template { + Template::render("image", get_post(conn, id).into_inner()) +} + /// Maybe initialize the directory for storing image symlinks and thumbnails. fn create_image_directory(conn: &DatabaseConnection) { fs::create_dir(&conn.image_dir).ok(); for image in conn.tb.images_by_tags(&vec![][..]).unwrap() { let src = Path::new(&image.orig_dir).join(&image.filename); - let dst = Path::new(&conn.image_dir).join(&image.filename); + let dst = image_store_filename(image.id, &image.filename); + let dst = Path::new(&conn.image_dir).join(dst); symlink(&src, &dst).ok(); - let stem = dst.file_stem().unwrap().to_str().unwrap(); - let thumb_path = Path::new(&conn.image_dir).join(&thumb_filename(&stem)); + let thumb_path = thumb_filename(image.id, &image.filename); + let thumb_path = Path::new(&conn.image_dir).join(&thumb_path); if !thumb_path.exists() { - let im = image::open(&Path::new(&src)).unwrap(); + let im = image::open(src).unwrap(); let out = &mut File::create(&thumb_path).unwrap(); im.thumbnail(100, 100) .write_to(out, ImageFormat::Png) @@ -208,8 +234,8 @@ fn main() { rocket::ignite() .mount("/public", StaticFiles::from("./static/")) .mount("/image", StaticFiles::from(&conn.image_dir)) - .mount("/", routes![index, display_posts]) - .mount("/api", routes![get_posts, put_posts]) + .mount("/", routes![index, display_posts, display_post]) + .mount("/api", routes![get_posts, get_post, put_post]) .attach(Template::fairing()) .manage(Mutex::new(conn)) .launch(); diff --git a/templates/image.hbs b/templates/image.hbs new file mode 100644 index 0000000..8c3ceb6 --- /dev/null +++ b/templates/image.hbs @@ -0,0 +1,35 @@ + + + + бирка-тян - {{ orig_filename }} + + + + +
+

бирка-тян

+
+
+

{{ orig_filename }}

+ +
+ + + diff --git a/templates/index.hbs b/templates/index.hbs index c3311b9..1279a5e 100644 --- a/templates/index.hbs +++ b/templates/index.hbs @@ -7,11 +7,11 @@
-

бирка-тян

+

бирка-тян

{{#each images}} - + {{/each}} {{#if next_page}}

next

@@ -26,7 +26,7 @@ -