summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/birka-web.rs49
-rw-r--r--templates/image.hbs13
2 files changed, 57 insertions, 5 deletions
diff --git a/src/birka-web.rs b/src/birka-web.rs
index 2053805..4e518aa 100644
--- a/src/birka-web.rs
+++ b/src/birka-web.rs
@@ -85,6 +85,26 @@ struct FileResult {
tags: Vec<String>,
}
+/// Return whether or not `filename` ends with one of `extensions`.
+fn has_extension<T: AsRef<Path>>(filename: T, extensions: Vec<&str>) -> bool {
+ filename
+ .as_ref()
+ .extension()
+ .and_then(|ext| ext.to_str())
+ .map(|ext| extensions.contains(&ext))
+ .unwrap_or(false)
+}
+
+/// Return whether or not `filename` ends with the extension of a known video file type.
+fn is_video<T: AsRef<Path>>(filename: T) -> bool {
+ has_extension(filename, vec!["mp4", "mkv", "webm"])
+}
+
+/// Return whether or not `filename` ends with the extension of a known image file type.
+fn is_image<T: AsRef<Path>>(filename: T) -> bool {
+ has_extension(filename, vec!["png", "jpg", "jpeg", "gif"])
+}
+
/// Return the store file name of `filename`.
fn store_filename<T: AsRef<Path>>(id: i64, path: T) -> String {
if let Some(filename) = path.as_ref().file_name() {
@@ -101,10 +121,10 @@ fn store_filename<T: AsRef<Path>>(id: i64, path: T) -> String {
/// Return the store file name of the thumbnail of `filename`.
fn thumb_filename<T: AsRef<Path>>(id: i64, path: T) -> String {
- if let Some(filename) = path.as_ref().file_name() {
- let filename = filename.to_string_lossy();
- if let Some(n) = filename.rfind('.') {
- format!("{id}_thumb.{ext}", id = id, ext = &filename[n + 1..])
+ if let Some(ext) = path.as_ref().extension() {
+ if let Some(ext) = ext.to_str() {
+ let ext = if is_video(path.as_ref()) { "png" } else { ext };
+ format!("{id}_thumb.{ext}", id = id, ext = ext)
} else {
format!("{}_thumb", id)
}
@@ -287,6 +307,9 @@ fn display_post(conn: SiteState, id: i64) -> Result<Template> {
tags: Vec<String>,
filename: String,
orig_filename: String,
+ is_image: bool,
+ is_video: bool,
+ is_unknown: bool,
}
let tb = &conn
@@ -304,6 +327,9 @@ fn display_post(conn: SiteState, id: i64) -> Result<Template> {
.ok_or(anyhow!("Could not parse filename"))?,
);
+ let is_image = is_image(&file.path);
+ let is_video = is_video(&file.path);
+
Ok(Template::render(
"image",
Context {
@@ -311,6 +337,9 @@ fn display_post(conn: SiteState, id: i64) -> Result<Template> {
orig_filename,
tags: file.tags,
filename: store_filename(file.id, &file.path),
+ is_image,
+ is_video,
+ is_unknown: !is_image && !is_video,
},
))
}
@@ -332,6 +361,18 @@ fn add_to_store(file: &database::File, file_dir: &str) {
im.thumbnail(100, 100)
.write_to(out, ImageFormat::Png)
.unwrap();
+ } else if is_video(&file.path) {
+ // FIXME: Can we do this... natively?
+ std::process::Command::new("ffmpeg")
+ .arg("-i")
+ .arg(&store_path)
+ .arg("-vframes")
+ .arg("1")
+ .arg("-s")
+ .arg("100x100")
+ .arg(&thumb_path)
+ .output()
+ .expect("failed to execute process");
} else {
let src = Path::new("./static/img/missing_thumb.png");
symlink(src.canonicalize().unwrap(), &thumb_path).unwrap();
diff --git a/templates/image.hbs b/templates/image.hbs
index ae24f06..7641820 100644
--- a/templates/image.hbs
+++ b/templates/image.hbs
@@ -11,7 +11,18 @@
</header>
<main>
<h2>{{ orig_filename }}</h2>
- <img src="/image/{{filename}}">
+ {{#if is_video}}
+ <video width="320" height="240" controls>
+ <source src="/image/{{filename}}">
+ Your browser does not support the video tag.
+ </video>
+ {{/if}}
+ {{#if is_image}}
+ <img src="/image/{{filename}}">
+ {{/if}}
+ {{#if is_unknown}}
+ <a href="/image/{{filename}}">Click here to view.</a>
+ {{/if}}
</main>
<aside id="tag-view">
<section id="search">