progress
This commit is contained in:
+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