1use rand::seq::SliceRandom;
2use rand::thread_rng;
3use serde::Serialize;
4use std::path::PathBuf;
5use walkdir::WalkDir;
6
7#[derive(Clone)]
9pub struct ImageDir {
10 pub path: PathBuf,
12 pub file_extension: String,
14}
15
16impl ImageDir {
17 pub fn find_images(&self) -> Vec<PathBuf> {
19 let mut img_files: Vec<PathBuf> = Vec::new();
20 for ent in WalkDir::new(self.path.as_os_str()).into_iter().flatten() {
21 let path = ent.path();
22 if path
23 .display()
24 .to_string()
25 .ends_with(format!(".{}", self.file_extension).as_str())
26 {
27 img_files.push(path.to_path_buf());
28 }
29 }
30 img_files
31 }
32
33 pub fn get_random_image(&self) -> PathBuf {
35 let mut imgs = self.find_images();
36 let mut rng = thread_rng();
37 imgs.shuffle(&mut rng);
38 imgs[0].clone()
39 }
40}
41
42#[derive(Serialize)]
45pub struct TransitionConfig {
46 pub imgs: Vec<PathBuf>,
47 pub title: String,
48 pub n_imgs: f32,
49 pub duration_per_image: usize,
50 pub transition_time: f32,
51 pub shuffle: bool,
53 pub static_route: String,
55}
56
57impl TransitionConfig {
58 pub fn new(imgs: Vec<PathBuf>, title: String, transition_time: usize, shuffle: bool) -> TransitionConfig {
60 let n_imgs: f32 = imgs.len() as f32;
64 let duration_per_image: usize = transition_time;
65 let transition_time: f32 = 2.0;
66 let static_route = String::from("static");
68 TransitionConfig {
69 imgs,
70 n_imgs,
71 title,
72 duration_per_image,
73 transition_time,
74 static_route,
75 shuffle,
76 }
77 }
78
79 pub fn generate_html(&self) -> anyhow::Result<String> {
82 let html_template = include_str!("../files/index.html.j2");
84 let mut context = tera::Context::new();
85 let imgs: Vec<_> = self
86 .imgs
87 .iter()
88 .map(|i| {
89 format!(
90 "{}/{}",
91 self.static_route,
92 i.file_name().unwrap_or_default().to_str().unwrap()
93 )
94 })
95 .collect();
96 context.insert("config", &self);
97 context.insert("imgs", &imgs);
98 context.insert("duration", &self.duration_per_image);
99 context.insert("shuffle_opt", &self.shuffle);
100 Ok(tera::Tera::one_off(html_template, &context, false)?)
101 }
102}
103
104#[cfg(test)]
105mod tests {
106 use super::*;
107 #[test]
108 fn basic_math() {
109 let mut imgs = Vec::new();
110 imgs.push(PathBuf::from("img/foo1.png"));
111 imgs.push(PathBuf::from("img/foo2.png"));
112 imgs.push(PathBuf::from("img/foo3.png"));
113 imgs.push(PathBuf::from("img/foo4.png"));
114 let c = TransitionConfig::new(imgs, "foo".to_string(), 5);
115 assert!(c.n_imgs == 4.0);
116 }
117
118 #[test]
119 fn create_image_dir() {
120 let d = String::from("img");
121 let _i = ImageDir {
122 path: d.into(),
123 file_extension: String::from("png"),
124 };
125 }
126}