progress
This commit is contained in:
@@ -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"
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"name": "New Document",
|
||||
"text": "# The effects of Whimsum dust:\nmore aggression, higher damage, higher rate of fire, lower accuracy"
|
||||
}
|
||||
@@ -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"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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."
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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"
|
||||
}
|
||||
}
|
||||
}
|
||||
+4
-2
@@ -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)
|
||||
|
||||
|
||||
+35
-2
@@ -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<RightPanelContent>, ui: &mut egui::Ui) {
|
||||
pub fn ui(
|
||||
&mut self,
|
||||
to_load: &mut Option<RightPanelContent>,
|
||||
load_doc: &mut Option<MainEditor>,
|
||||
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<Vec<MainEditor>> {
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
+9
-2
@@ -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<PathBuf> = 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<RightPanelContent> = None;
|
||||
let mut load_doc: Option<MainEditor> = 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
|
||||
|
||||
+108
-5
@@ -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<Self, Box<dyn std::error::Error>> {
|
||||
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<dyn std::error::Error>> {
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user