diff --git a/src/editors/note_editor.rs b/src/editors/note_editor.rs index fd76910..83a7658 100644 --- a/src/editors/note_editor.rs +++ b/src/editors/note_editor.rs @@ -79,11 +79,31 @@ impl Note { util::saved_status(ui, self.saved, &self.id, &self.name); - if ui.button("Save").clicked() { - if let Err(e) = self.save() { - eprintln!("Failed to save: {e}"); + ui.horizontal(|ui| { + if ui.button("Save").clicked() { + if let Err(e) = self.save() { + eprintln!("Failed to save: {e}"); + } } - } + + if ui.button("Create Copy").clicked() { + let new_id = uuid::Uuid::new_v4().to_string(); + let mut new_note = self.clone(); + new_note.id = new_id; + new_note.name = format!("{} (Copy)", self.name); + if let Err(e) = new_note.save() { + eprintln!("Failed to save copy: {e}"); + } + } + + if ui.button("Delete").clicked() { + if let Err(e) = + FILESYSTEM.delete(Path::new(&format!("notes/{id}.json", id = self.id))) + { + eprintln!("Failed to delete: {e}"); + } + } + }); let id = ui.make_persistent_id("note_name"); egui::collapsing_header::CollapsingState::load_with_default_open(ui.ctx(), id, true) diff --git a/src/explorer.rs b/src/explorer.rs index ec762ed..fa3449f 100644 --- a/src/explorer.rs +++ b/src/explorer.rs @@ -1,7 +1,4 @@ -use itertools::Itertools; -use std::fs::{self, DirEntry}; - -// use walkdir::{DirEntry, WalkDir}; +use std::path::Path; use crate::{ PROJECT_FOLDER, RightPanelContent, @@ -10,6 +7,7 @@ use crate::{ asset_editor::Asset, content_editor::ContentSection, object_editor::ObjectInstance, tags::Tag, template_editor::Template, }, + filesystem::{FILESYSTEM, FsError, LegacyFileSystem}, note_editor::Note, }; @@ -165,14 +163,6 @@ impl Explorer { }); } - /// Recursively renders a tree of documents. - /// - /// Each document is represented by a single element in the `documents` array. - /// The `parent_id` parameter is used to filter out documents that do not have the current - /// parent. If `parent_id` is `None`, all documents are rendered. - /// - /// `load_doc` is a mutable reference to a `MainEditor`. When a document is clicked, it - /// is loaded into the `MainEditor` and returned as `Some`. fn render_doc_branch( ui: &mut egui::Ui, documents: &[ContentSection], @@ -241,95 +231,64 @@ impl Explorer { } fn render_assets(&mut self, ui: &mut egui::Ui, to_load: &mut Option) { + Self::render_asset_dir(ui, to_load, Path::new("assets")); + } + + fn render_asset_dir(ui: &mut egui::Ui, to_load: &mut Option, path: &Path) { + let files = FILESYSTEM.lsfiles(path).unwrap(); + let dirs = FILESYSTEM.lsdirs(path).unwrap(); + + let file_name = path.file_name().unwrap().to_str().unwrap().to_string(); + egui::collapsing_header::CollapsingState::load_with_default_open( ui.ctx(), - ui.make_persistent_id("assets"), - true, + ui.make_persistent_id(&file_name), + false, ) .show_header(ui, |ui| { ui.horizontal(|ui| { - ui.label("Assets"); + ui.label(file_name); + let _clicked = ui.button("+").on_hover_text("Add new item").clicked(); }); }) .body(|ui| { - let entries = fs::read_dir(PROJECT_FOLDER.join("assets")) - .unwrap() - .filter_map(Result::ok) - .sorted_by(|a, b| { - // Directories first, then files - let a_is_dir = a.file_type().unwrap().is_dir(); - let b_is_dir = b.file_type().unwrap().is_dir(); - if a_is_dir == b_is_dir { - a.file_name().cmp(&b.file_name()) - } else if a_is_dir { - std::cmp::Ordering::Less - } else { - std::cmp::Ordering::Greater - } - }) - .collect::>(); + // recursive call to render the next level of documents + for dir in dirs.iter() { + Self::render_asset_dir(ui, to_load, dir); + } - for entry in entries { - Self::render_entry(ui, to_load, &entry); + for file in files.iter() { + Self::render_asset(ui, to_load, file); } }); } - fn render_entry(ui: &mut egui::Ui, to_load: &mut Option, entry: &DirEntry) { - let file_type = entry.file_type().unwrap(); - let is_dir = file_type.is_dir(); - let file_name = entry.file_name().to_str().unwrap().to_string(); - let path = entry.path(); + fn render_asset(ui: &mut egui::Ui, to_load: &mut Option, path: &Path) { + let file_name = path.file_name().unwrap().to_str().unwrap().to_string(); - if is_dir { - let entries = fs::read_dir(path) - .unwrap() - .filter_map(Result::ok) - .collect::>(); - - egui::collapsing_header::CollapsingState::load_with_default_open( - ui.ctx(), - ui.make_persistent_id(&file_name), - false, - ) - .show_header(ui, |ui| { - ui.horizontal(|ui| { - ui.label(file_name); - let _clicked = ui.button("+").on_hover_text("Add new item").clicked(); - }); - }) - .body(|ui| { - // recursive call to render the next level of documents - for entry in entries { - Self::render_entry(ui, to_load, &entry); - } - }); - } else { - // Handle file - if ui - .selectable_label(false, format!("πŸ“„ {file_name}")) - .clicked() - { - // use asset::load to get the file at the path - let asset_path = path.strip_prefix(PROJECT_FOLDER.join("assets")).unwrap(); - let asset = Asset::open(asset_path.to_string_lossy().to_string()); - *to_load = Some(RightPanelContent::Asset(Box::new(asset))); - } + if ui + .selectable_label(false, format!("πŸ“„ {file_name}")) + .clicked() + { + // use asset::load to get the file at the path + let asset_path = path.strip_prefix(PROJECT_FOLDER.join("assets")).unwrap(); + let asset = Asset::open(asset_path.to_string_lossy().to_string()); + *to_load = Some(RightPanelContent::Asset(Box::new(asset))); } } // load templates from the templates folder - fn load_templates(&mut self) -> std::io::Result<()> { - let templates_folder = PROJECT_FOLDER.join("templates"); - if !templates_folder.exists() { - std::fs::create_dir_all(&templates_folder)?; + fn load_templates(&mut self) -> Result<(), FsError> { + let path = Path::new("templates"); + + if !FILESYSTEM.exists(path) { + FILESYSTEM.mkdir(path)?; } let mut templates = Vec::new(); - for entry in std::fs::read_dir(&templates_folder).unwrap() { - let path = entry.unwrap().path(); - match Template::load(path.file_stem().unwrap().to_str().unwrap()) { + for entry in FILESYSTEM.lsfiles(path)? { + match FILESYSTEM.read::