use std::collections::BTreeMap; use std::fs::{File, self}; use std::path::{Path, PathBuf}; use eframe::egui; #[derive(Default)] pub struct SlugPrompter { id_to_stamp_map: BTreeMap, id_to_slug_map: BTreeMap>, slug_to_id_map: BTreeMap, current_id: usize, current_slug: String, current_err: Option, cache_dir: PathBuf, file_path: PathBuf } impl SlugPrompter { pub fn run(locale: String, repo_dir: &Path, stamps: Vec) { let file_path = repo_dir.join(format!("slugs_{locale}.json")); let id_to_slug_map: BTreeMap>; if fs::exists(&file_path).unwrap() { id_to_slug_map = serde_json::from_reader( File::open(&file_path) .unwrap()) .unwrap(); } else { id_to_slug_map = Default::default(); } let native_options = eframe::NativeOptions::default(); eframe::run_native( &format!("Check Slugs for {locale} locale"), native_options, Box::new(|cc| Ok(Box::new(SlugPrompter::new(cc, id_to_slug_map, stamps, repo_dir.join("stamps_cache").join(&locale), file_path))))); } fn new(_cc: &eframe::CreationContext<'_>, id_to_slug_map: BTreeMap>, stamps: Vec, cache_dir: PathBuf, file_path: PathBuf) -> Self { let current_id = stamps[0].id; let slug_to_id_map = id_to_slug_map.clone().into_iter().filter_map(|(a, b)| b.map(|b2| (b2, a))).collect(); let id_to_stamp_map = stamps.into_iter().map(|stamp| (stamp.id, stamp)).collect(); SlugPrompter { id_to_stamp_map, id_to_slug_map, slug_to_id_map, cache_dir, file_path, current_id, current_slug: String::new(), current_err: None } } fn write_file(&self) { serde_json::to_writer_pretty(File::create(&self.file_path).unwrap(), &self.id_to_slug_map); } } impl eframe::App for SlugPrompter { fn update(&mut self, ctx: &egui::Context, frame: &mut eframe::Frame) { if self.id_to_slug_map.contains_key(&self.current_id) { let mut hit = false; for id in self.id_to_stamp_map.keys() { if !self.id_to_slug_map.contains_key(id) { hit = true; self.current_id = *id; self.current_slug = String::new(); self.current_err = None; break } } if !hit { ctx.send_viewport_cmd(egui::viewport::ViewportCommand::Close); return } } egui_extras::install_image_loaders(ctx); egui::CentralPanel::default().show(ctx, |ui| { let image_path = format!("file://{}", self .cache_dir .join(&self.id_to_stamp_map[&self.current_id].assetbundle_name) .with_extension("png") .display()); ui.add( egui::Image::new(image_path) .max_width(200.0) ); ui.horizontal(|ui| { ui.label("Builtin name:"); ui.strong( self .id_to_stamp_map[&self.current_id] .name .split("]").nth(1).unwrap() .trim()); }); let text_res = ui.text_edit_singleline(&mut self.current_slug); ui.label(format!("{}/{}", self.id_to_slug_map.len(), self.id_to_stamp_map.len())); if let Some(s) = self.current_err.as_ref() { ui.colored_label(egui::Color32::RED, s); } if ui.button("Confirm").clicked() || text_res.lost_focus() && ui.input(|i| i.key_pressed(egui::Key::Enter)) { if self.slug_to_id_map.contains_key(&self.current_slug) { self.current_err = Some(format!("Slug \"{}\" already taken by {}!", self.current_slug, self.slug_to_id_map[&self.current_slug])); } else { if self.current_slug == "" { self.id_to_slug_map.insert(self.current_id, None); } else { self.slug_to_id_map.insert(self.current_slug.clone(), self.current_id); self.id_to_slug_map.insert(self.current_id, Some(self.current_slug.clone())); } self.write_file(); } } }); } }