use crate::model::state::State;
use crate::model::{settings, state};
use artifact::project::fs;
use std::{
io::{self, Write as _},
path::{Path, PathBuf},
time::{Duration, SystemTime},
};
type File = (&'static str, &'static [u8]);
macro_rules! file {
($path:literal) => {
(
$path,
include_bytes!(concat!(
env!("CARGO_MANIFEST_DIR"),
"/assets/welcome/.cydonia/",
$path
)) as &[u8],
)
};
}
const SEED: &[&[File]] = &[
&[file!("boards/1789958240578.toml")],
&[
file!("articles/1789958235652/content.md"),
file!("articles/1789958235652/properties.toml"),
file!("articles/1789958235652/cover-833563.svg"),
],
&[
file!("articles/1789958219063/content.md"),
file!("articles/1789958219063/properties.toml"),
],
];
const LANDING: &str = "articles/1789958219063/content.md";
const APART: Duration = Duration::from_secs(1);
pub fn path() -> Option<PathBuf> {
settings::data_dir().ok().map(|dir| dir.join("welcome"))
}
pub fn seed(state: &mut State) {
if state::path().is_none_or(|path| path.exists()) {
return;
}
let Some(root) = path() else {
return;
};
if !root.is_dir() && write(&root).is_err() {
return;
}
state.last.insert(
root.clone(),
state::Entry {
kind: state::Kind::Article,
id: fs::Project::new(&root)
.cydonia()
.join(LANDING)
.to_string_lossy()
.into_owned(),
},
);
state.projects.insert(0, root);
state.active = 0;
}
fn write(root: &Path) -> io::Result<()> {
let dir = fs::Project::new(root).init()?;
let span = APART * SEED.len() as u32;
let base = SystemTime::now()
.checked_sub(span)
.unwrap_or(SystemTime::UNIX_EPOCH);
for (step, entry) in SEED.iter().enumerate() {
let stamp = base + APART * step as u32;
for (name, bytes) in *entry {
let path = dir.join(name);
if let Some(parent) = path.parent() {
std::fs::create_dir_all(parent)?;
}
let mut file = std::fs::File::create(&path)?;
file.write_all(bytes)?;
file.set_modified(stamp)?;
}
}
Ok(())
}
#[cfg(test)]
#[path = "../../tests/unit/welcome.rs"]
mod tests;