This commit is contained in:
2025-07-15 17:13:35 +01:00
parent 1117ce9f13
commit fe8bbae68e
11 changed files with 201 additions and 49 deletions
+35 -2
View File
@@ -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
View File
@@ -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
View File
@@ -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;
}
}