use std::{ io::Cursor, path::PathBuf }; use crate::app::{ build::{docki_build, DockiBuildResult}, fs_util::{self, create_dir_recursive}, log::display_status, }; pub struct BuildExecution { progress: usize, goal: usize, } impl BuildExecution { pub fn new() -> Self { return BuildExecution { progress: 0, goal: 0, }; } pub async fn execute(&mut self, offline_reveal: bool) -> Result<(), String> { let path = "./docs/".to_string(); if !fs_util::directory_exists(&path) { return Err( "docs directory does not exist it. Create it or use the template".to_string(), ); } if let Err(error) = Self::prepare(offline_reveal).await { return Err(error); } return self.build_dir(&path, offline_reveal); } async fn prepare(offline_reveal: bool) -> Result<(), String> { if !offline_reveal { return Ok(()) } let reveal_version = "5.2.1"; let target = format!("https://github.com/hakimel/reveal.js/archive/{reveal_version}.zip"); create_dir_recursive("./docs/slides"); reqwest::get(target.clone()).await.unwrap(); let Ok(response) = reqwest::get(target).await else { return Err("could not downlaod revealjs".to_string()) }; let Ok(bytes) = response.bytes().await else { return Err("could not extract bytes".to_string()) }; let out = PathBuf::from("./docs/slides/revealjs"); if zip_extract::extract(Cursor::new(bytes), &out, true).is_err() { return Err("could not write extracted archive to disk".to_string()); } return Ok(()); } fn build_dir(&mut self, path: &str, offline_reveal: bool) -> Result<(), String> { let result = fs_util::fetch_paths_recursive(&path); let Ok(paths) = result else { return Err(result.unwrap_err()) }; for (index, in_path) in paths.iter().enumerate() { self.progress = index + 1; self.goal = paths.len(); let result = docki_build(&in_path, offline_reveal); match result { DockiBuildResult::Err(err) => { self.display_building_status("Error", in_path, ""); println!("{}", err) }, DockiBuildResult::Copy(out_path) => self.display_building_status("Copy", &in_path, &out_path), DockiBuildResult::Slide(out_path) => self.display_building_status("Slide", &in_path, &out_path), DockiBuildResult::Doc(out_path) => self.display_building_status("Doc", &in_path, &out_path), DockiBuildResult::Silent => () } } return Ok(()); } fn display_building_status(&self, status_type: &str, in_path: &str, out_path: &str) -> () { let progress_str = format!("{} / {}", self.progress, self.goal); display_status(&progress_str, status_type, in_path, out_path); } }