From fe8bbae68eb082e8fdd294f5be0a0a8050f9bf0c Mon Sep 17 00:00:00 2001 From: zxq5 Date: Tue, 15 Jul 2025 17:13:35 +0100 Subject: [PATCH] progress --- Cargo.toml | 5 + .../09fb1e02-055b-4a02-b23e-5e5e9e0ca52d.json | 4 + .../0078bb24-2fb0-4ecb-b5cb-20d29c5f2f77.json | 10 ++ .../20beeb2f-363c-49bf-9621-f156d7c7cdd7.json | 10 ++ .../67e29043-9aa8-4dd9-807c-cc7385eb6847.json | 16 --- .../bd13d252-3f19-4618-bb10-cc45e9f7d301.json | 16 +++ .../d1b10e0c-f6b4-4b9d-a96e-cb51213f0243.json | 22 ---- roadmap.md | 6 +- src/explorer.rs | 37 +++++- src/main.rs | 11 +- src/main_editor.rs | 113 +++++++++++++++++- 11 files changed, 201 insertions(+), 49 deletions(-) create mode 100644 project/documents/09fb1e02-055b-4a02-b23e-5e5e9e0ca52d.json create mode 100644 project/objects/0078bb24-2fb0-4ecb-b5cb-20d29c5f2f77.json create mode 100644 project/objects/20beeb2f-363c-49bf-9621-f156d7c7cdd7.json delete mode 100644 project/objects/67e29043-9aa8-4dd9-807c-cc7385eb6847.json create mode 100644 project/objects/bd13d252-3f19-4618-bb10-cc45e9f7d301.json delete mode 100644 project/objects/d1b10e0c-f6b4-4b9d-a96e-cb51213f0243.json diff --git a/Cargo.toml b/Cargo.toml index d67336c..5409042 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -22,3 +22,8 @@ thiserror = "2.0.12" egui_commonmark = { version = "0.20.0", features = ["embedded_image"] } walkdir = "2.5.0" uuid = { version = "1.17.0", features = ["v4"] } + + +[target.x86_64-pc-windows-gnu] +linker = "x86_64-w64-mingw32-gcc" +ar = "x86_64-w64-mingw32-gcc-ar" diff --git a/project/documents/09fb1e02-055b-4a02-b23e-5e5e9e0ca52d.json b/project/documents/09fb1e02-055b-4a02-b23e-5e5e9e0ca52d.json new file mode 100644 index 0000000..1eba827 --- /dev/null +++ b/project/documents/09fb1e02-055b-4a02-b23e-5e5e9e0ca52d.json @@ -0,0 +1,4 @@ +{ + "name": "New Document", + "text": "# The effects of Whimsum dust:\nmore aggression, higher damage, higher rate of fire, lower accuracy" +} \ No newline at end of file diff --git a/project/objects/0078bb24-2fb0-4ecb-b5cb-20d29c5f2f77.json b/project/objects/0078bb24-2fb0-4ecb-b5cb-20d29c5f2f77.json new file mode 100644 index 0000000..f7a5ad4 --- /dev/null +++ b/project/objects/0078bb24-2fb0-4ecb-b5cb-20d29c5f2f77.json @@ -0,0 +1,10 @@ +{ + "id": "0078bb24-2fb0-4ecb-b5cb-20d29c5f2f77", + "template_id": "b5745688-3c1c-40de-bc3a-2a3e354dd19d", + "name": "The SPOONS!", + "fields": { + "description": { + "value": "full of smilers\n" + } + } +} \ No newline at end of file diff --git a/project/objects/20beeb2f-363c-49bf-9621-f156d7c7cdd7.json b/project/objects/20beeb2f-363c-49bf-9621-f156d7c7cdd7.json new file mode 100644 index 0000000..5f08197 --- /dev/null +++ b/project/objects/20beeb2f-363c-49bf-9621-f156d7c7cdd7.json @@ -0,0 +1,10 @@ +{ + "id": "20beeb2f-363c-49bf-9621-f156d7c7cdd7", + "template_id": "b5745688-3c1c-40de-bc3a-2a3e354dd19d", + "name": "the brewdog.", + "fields": { + "description": { + "value": "full of smilers\n" + } + } +} \ No newline at end of file diff --git a/project/objects/67e29043-9aa8-4dd9-807c-cc7385eb6847.json b/project/objects/67e29043-9aa8-4dd9-807c-cc7385eb6847.json deleted file mode 100644 index d23a7e2..0000000 --- a/project/objects/67e29043-9aa8-4dd9-807c-cc7385eb6847.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "id": "67e29043-9aa8-4dd9-807c-cc7385eb6847", - "template_id": "c96f5e87-7517-44cc-a5ab-42ffd537801d", - "name": "sword", - "fields": { - "durability": { - "value": "8.6" - }, - "Icon": { - "value": "/home/zxq5/Projects/Minecraft/Packs/ZXQ5 projects/ZXQ5 x/ZXQ5 x-512/ZXQ5 x Release/classic.pack.png" - }, - "description": { - "value": "idk" - } - } -} \ No newline at end of file diff --git a/project/objects/bd13d252-3f19-4618-bb10-cc45e9f7d301.json b/project/objects/bd13d252-3f19-4618-bb10-cc45e9f7d301.json new file mode 100644 index 0000000..9d1850a --- /dev/null +++ b/project/objects/bd13d252-3f19-4618-bb10-cc45e9f7d301.json @@ -0,0 +1,16 @@ +{ + "id": "bd13d252-3f19-4618-bb10-cc45e9f7d301", + "template_id": "c96f5e87-7517-44cc-a5ab-42ffd537801d", + "name": "Cast Iron Pan", + "fields": { + "durability": { + "value": "9999999" + }, + "Icon": { + "value": "" + }, + "description": { + "value": "An unburnt pan for bitchslapping, comes with a free punchcard." + } + } +} \ No newline at end of file diff --git a/project/objects/d1b10e0c-f6b4-4b9d-a96e-cb51213f0243.json b/project/objects/d1b10e0c-f6b4-4b9d-a96e-cb51213f0243.json deleted file mode 100644 index 1168151..0000000 --- a/project/objects/d1b10e0c-f6b4-4b9d-a96e-cb51213f0243.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "id": "d1b10e0c-f6b4-4b9d-a96e-cb51213f0243", - "template_id": "a24b3ab7-2572-4af4-8457-df26937fd773", - "name": "zxq5", - "fields": { - "Personality": { - "value": "coder" - }, - "Portrait / Image": { - "value": "/home/fantasypvp/Pictures/logos and pfps/YT profile picture background.png" - }, - "Appearance": { - "value": "taller than panic" - }, - "Age": { - "value": "19" - }, - "Date of Birth": { - "value": "2025-07-15" - } - } -} \ No newline at end of file diff --git a/roadmap.md b/roadmap.md index 6eb6aaa..09bb0af 100644 --- a/roadmap.md +++ b/roadmap.md @@ -10,13 +10,15 @@ - [x] Edit template - [x] Save template - [x] Load template - - [ ] Delete template + - [x] Delete template + - [x] Create copy of template - [x] Objects - [x] Create object from template - [x] Save object - [x] Load object - [x] View & Edit Object - - [ ] Delete object + - [x] Delete object + - [x] Create copy of object - [x] Projects - [x] Single project folder (hardcoded at current directory) diff --git a/src/explorer.rs b/src/explorer.rs index 95c3fe3..316772d 100644 --- a/src/explorer.rs +++ b/src/explorer.rs @@ -2,6 +2,7 @@ use egui::RichText; use crate::{ PROJECT_FOLDER, RightPanelContent, + main_editor::MainEditor, note::Note, object::ObjectInstance, template::{FieldType, Template}, @@ -14,7 +15,12 @@ impl Explorer { Self {} } - pub fn ui(&mut self, to_load: &mut Option, ui: &mut egui::Ui) { + pub fn ui( + &mut self, + to_load: &mut Option, + load_doc: &mut Option, + ui: &mut egui::Ui, + ) { let (templates, objects) = match Self::load_templates() { Ok((templates, objects)) => (templates, objects), Err(e) => { @@ -116,7 +122,20 @@ impl Explorer { } }); - egui::CollapsingHeader::new("Projects").show(ui, |ui| {}); + let documents = Self::load_documents().unwrap(); + + egui::CollapsingHeader::new("Projects").show(ui, |ui| { + for document in &documents { + ui.horizontal(|ui| { + ui.add_space(10.0); + + // load the document + if ui.selectable_label(false, &document.name).clicked() { + *load_doc = Some(document.clone()); + } + }); + } + }); }); } @@ -156,4 +175,18 @@ impl Explorer { Ok(notes) } + + fn load_documents() -> std::io::Result> { + let mut documents = Vec::new(); + + for entry in std::fs::read_dir(PROJECT_FOLDER.join("documents")).unwrap() { + let path = entry.unwrap().path(); + match MainEditor::load(path.file_stem().unwrap().to_str().unwrap()) { + Ok(document) => documents.push(document), + Err(err) => eprintln!("Could not parse file {path:?}: {err}"), + } + } + + Ok(documents) + } } diff --git a/src/main.rs b/src/main.rs index 7af5d8e..c620acc 100644 --- a/src/main.rs +++ b/src/main.rs @@ -13,7 +13,7 @@ use egui_file::DialogType; use object::ObjectInstance; use template::{FieldType, Template}; -use crate::{explorer::Explorer, note::Note}; +use crate::{explorer::Explorer, main_editor::MainEditor, note::Note}; static PROJECT_FOLDER: LazyLock = LazyLock::new(|| { let mut path = std::env::current_dir().unwrap(); @@ -147,14 +147,21 @@ impl eframe::App for Interface { ui.separator(); let mut to_load: Option = None; + let mut load_doc: Option = None; ScrollArea::vertical().show(ui, |ui| { - self.explorer.ui(&mut to_load, ui); + self.explorer.ui(&mut to_load, &mut load_doc, ui); }); if let Some(to_load) = to_load { self.right_panel_content = to_load; } + + if let Some(load_doc) = load_doc { + self.editor = load_doc; + self.editor.show_editor = true; + self.editor.show_preview = true; + } }); // Main content area diff --git a/src/main_editor.rs b/src/main_editor.rs index d598572..15dfd6a 100644 --- a/src/main_editor.rs +++ b/src/main_editor.rs @@ -1,32 +1,133 @@ -use egui::{TextEdit, Ui}; +use egui::{RichText, TextEdit, Ui}; use egui_commonmark::{CommonMarkCache, CommonMarkViewer}; +use serde::{self, Deserialize, Serialize}; +use crate::PROJECT_FOLDER; + +#[derive(Serialize, Deserialize)] pub struct MainEditor { + pub name: String, + pub text: String, + #[serde(skip)] + pub id: String, + + #[serde(skip)] + saved: bool, + #[serde(skip)] pub show_editor: bool, + #[serde(skip)] pub show_preview: bool, - text: String, + #[serde(skip)] preview_cache: CommonMarkCache, } +impl Clone for MainEditor { + fn clone(&self) -> Self { + Self { + name: self.name.clone(), + text: self.text.clone(), + id: self.id.clone(), + saved: self.saved, + show_editor: self.show_editor, + show_preview: self.show_preview, + preview_cache: CommonMarkCache::default(), + } + } +} + impl MainEditor { pub fn new() -> Self { Self { + text: String::new(), + id: uuid::Uuid::new_v4().to_string(), + name: "New Document".to_string(), + saved: false, show_editor: false, // Start with editor hidden show_preview: true, - text: String::new(), preview_cache: CommonMarkCache::default(), } } + pub fn load(id: &str) -> Result> { + let path = PROJECT_FOLDER + .join("documents") + .join(format!("{}.json", id)); + + let content = std::fs::read_to_string(&path)?; + let mut editor: Self = serde_json::from_str(&content)?; + editor.saved = true; + editor.id = id.to_string(); + Ok(editor) + } + + pub fn save(&mut self) -> Result<(), Box> { + let path = PROJECT_FOLDER + .join("documents") + .join(format!("{}.json", &self.id)); + + let content = serde_json::to_string_pretty(self)?; + std::fs::write(path, content)?; + self.saved = true; + Ok(()) + } + pub fn ui(&mut self, ctx: &egui::Context) { // Show the editor window if enabled - if self.show_editor { + let mut show = self.show_editor; + if show { egui::Window::new("Markdown Editor") .resizable(true) .default_width(1000.0) .default_height(800.0) - .open(&mut self.show_editor) + .open(&mut show) .show(ctx, |ui| { + ui.vertical(|ui| { + ui.group(|ui| { + ui.horizontal(|ui| { + if self.saved { + ui.label(RichText::new("✓ Saved").color(egui::Color32::GREEN)); + } else { + ui.label( + RichText::new("* Unsaved").color(egui::Color32::YELLOW), + ); + } + ui.label(format!("id: {}", self.id)); + }); + }); + + // Save/Cancel buttons + 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 mut copy = self.clone(); + copy.id = uuid::Uuid::new_v4().to_string(); + copy.name = format!("{} (Copy)", self.name); + copy.save().unwrap(); + } + + if ui.button("Delete").clicked() { + std::fs::remove_file( + PROJECT_FOLDER + .join("documents") + .join(format!("{}.json", self.id)), + ) + .unwrap(); + + *self = Self::new(); + } + + if ui.button("Revert changes").clicked() { + // load default state + *self = Self::load(&self.id).unwrap(); + } + }); + }); + ui.horizontal(|ui| { ui.label("Content Editor"); ui.checkbox(&mut self.show_preview, "Preview"); @@ -104,5 +205,7 @@ impl MainEditor { }); }); } + + self.show_editor = show; } }