use crate::{MainWindow, TemplateCardData};
use slint::{ComponentHandle as _, ModelRc, SharedString, VecModel};
use std::path::{Path, PathBuf};
pub(in crate::gui::editor) fn setup_template_gallery(ui: &MainWindow) {
let mut cards = vec![TemplateCardData {
name: SharedString::from("Empty"),
shape: SharedString::from("Blank design"),
description: SharedString::from("No starting tiers -- author the schedule from scratch."),
ready: true,
}];
for spec in indicatrix_cut_core::templates::TEMPLATES {
cards.push(TemplateCardData {
name: SharedString::from(spec.name),
shape: SharedString::from(spec.shape),
description: SharedString::from(spec.description),
ready: true,
});
}
ui.global::<crate::TemplateGalleryModel>()
.set_templates(ModelRc::new(VecModel::from(cards)));
}
#[must_use]
#[cfg_attr(
not(test),
expect(
dead_code,
reason = "not yet called from non-test code: the render call this path feeds is a documented follow-up, see this fn's own doc comment"
)
)]
pub(in crate::gui::editor) fn thumbnail_cache_path(
cache_dir: &Path,
template_name: &str,
) -> PathBuf {
let slug: String = template_name
.chars()
.map(|c| {
if c.is_ascii_alphanumeric() {
c.to_ascii_lowercase()
} else {
'-'
}
})
.collect();
let mut collapsed = String::with_capacity(slug.len());
let mut last_dash = false;
for c in slug.chars() {
if c == '-' {
if !last_dash {
collapsed.push(c);
}
last_dash = true;
} else {
collapsed.push(c);
last_dash = false;
}
}
let trimmed = collapsed.trim_matches('-');
cache_dir
.join("thumbnail-cache")
.join(format!("{trimmed}.png"))
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn thumbnail_cache_path_is_stable_and_collision_free() {
let dir = Path::new("/app-data");
assert_eq!(
thumbnail_cache_path(dir, "Standard Round Brilliant"),
dir.join("thumbnail-cache")
.join("standard-round-brilliant.png")
);
assert_eq!(
thumbnail_cache_path(dir, "Round Brilliant -- Shallow Pavilion"),
dir.join("thumbnail-cache")
.join("round-brilliant-shallow-pavilion.png")
);
let a = thumbnail_cache_path(dir, "Round Brilliant -- Shallow Pavilion");
let b = thumbnail_cache_path(dir, "Round Brilliant -- Deep Pavilion");
assert_ne!(a, b);
}
#[test]
fn thumbnail_cache_path_never_starts_or_ends_with_a_dash() {
let dir = Path::new("/app-data");
let path = thumbnail_cache_path(dir, " Weird -- Name!! ");
let name = path.file_stem().unwrap().to_string_lossy().into_owned();
assert!(!name.starts_with('-'));
assert!(!name.ends_with('-'));
}
}