note-taking/src/main.rs

221 lines
7.4 KiB
Rust
Raw Normal View History

#![cfg_attr(
all(
target_os = "windows",
not(debug_assertions),
),
windows_subsystem = "windows"
)]
2023-02-27 14:31:17 +00:00
use std::collections::{VecDeque};
use std::fs;
use std::time::SystemTime;
use directories::ProjectDirs;
2023-02-27 17:57:20 +00:00
use eframe::{CreationContext, Frame};
use egui::{Context, RichText, TextEdit, Widget};
use log::info;
use simple_logger::SimpleLogger;
use crate::notes::{Note, NoteMetadata};
use crate::saving::Saving;
mod notes;
mod saving;
#[derive(PartialEq)]
enum CurrentMode {
View,
Compose,
PasswordInput,
}
struct App {
notes: Vec<Note>,
update_notes_next: bool,
password: Option<String>,
tested_password: bool,
mode: CurrentMode,
saving: Saving,
password_buffer: String,
title_buffer: String,
text_buffer: String,
}
2023-02-27 17:57:20 +00:00
impl App {
fn new(_cc: &CreationContext<'_>, notes: Vec<Note>, saving: Saving) -> Self {
Self {
password: None,
update_notes_next: false,
tested_password: false,
notes,
mode: CurrentMode::PasswordInput,
saving,
password_buffer: String::new(),
title_buffer: String::new(),
text_buffer: String::new(),
}
}
}
fn main() {
SimpleLogger::new().init().expect("failed to initialize logger");
info!("starting the UI");
let options = eframe::NativeOptions {
initial_window_size: Some(egui::vec2(640.0, 640.0)),
..Default::default()
};
let project_directories = ProjectDirs::from("com", "sofiaritz", "notes")
.unwrap();
let data_directory = project_directories
.data_dir();
info!("data directory: {:?}", data_directory);
fs::create_dir_all(data_directory).unwrap();
info!("created all intermediate directories");
let saving = Saving::new(data_directory);
let notes = saving.read_notes().unwrap();
info!("successfully read initial notes");
eframe::run_native(
"notes",
options,
2023-02-27 17:57:20 +00:00
Box::new(move |cc| Box::new(App::new(cc, notes, saving)))
).expect("failed to run native");
info!("shutdown");
}
impl eframe::App for App {
fn update(&mut self, ctx: &Context, _frame: &mut Frame) {
if self.password.is_none() {
self.mode = CurrentMode::PasswordInput;
}
if !self.tested_password && self.password.is_some() {
if let Some(note) = self.notes.get(0) {
note.decrypt(self.password.as_ref().unwrap()).unwrap();
self.tested_password = true;
}
}
if self.update_notes_next {
self.notes = self.saving.read_notes().unwrap();
self.update_notes_next = false;
info!("reloaded notes");
}
match self.mode {
CurrentMode::View => {
let password = self.password.as_ref().unwrap();
egui::CentralPanel::default().show(ctx, |ui| {
ui.heading("notes");
ui.horizontal(|ui| {
ui.label("the simple note taking app that uses encryption by default");
ui.add_space(7.5);
if ui.button("want to add one note?").clicked() {
self.mode = CurrentMode::Compose;
}
});
ui.separator();
2023-02-27 16:16:04 +00:00
egui::ScrollArea::vertical().show(ui, |ui| {
for note in &mut self.notes {
let render_result = note.render(ui, password, |id| {
let _ = &self.saving.delete_note(&id).unwrap();
info!("note with id {} was successfully deleted", id);
self.update_notes_next = true;
});
if let Some(new_note) = render_result {
*note = new_note;
}
ui.add_space(10.0);
}
2023-02-27 16:16:04 +00:00
});
});
}
CurrentMode::Compose => {
let password = self.password.as_ref().unwrap();
egui::CentralPanel::default().show(ctx, |ui| {
ui.heading("notes");
ui.horizontal(|ui| {
ui.label("the simple note taking app that uses encryption by default");
ui.add_space(7.5);
if ui.button("return to view mode?").clicked() {
self.title_buffer = String::new();
self.text_buffer = String::new();
self.mode = CurrentMode::View;
}
});
ui.separator();
2023-02-27 16:16:04 +00:00
egui::ScrollArea::vertical().show(ui, |ui| {
ui.label("title:");
ui.text_edit_singleline(&mut self.title_buffer);
ui.label("text:");
ui.text_edit_multiline(&mut self.text_buffer);
ui.add_space(10.0);
if ui.button("add note").clicked() {
let note = Note::Decrypted {
id: SystemTime::now()
.duration_since(SystemTime::UNIX_EPOCH)
.unwrap()
.as_millis()
.to_string(),
title: self.title_buffer.clone(),
metadata: NoteMetadata {
date: SystemTime::now(),
arbitrary: None,
},
text: self.text_buffer.clone(),
};
self.saving.save_note(note.clone(), password.to_string()).unwrap();
let mut vec_deque = VecDeque::from(self.notes.clone());
vec_deque.push_front(note);
self.notes = Vec::from(vec_deque);
self.title_buffer = String::new();
self.text_buffer = String::new();
self.mode = CurrentMode::View;
}
});
});
}
CurrentMode::PasswordInput => {
egui::CentralPanel::default().show(ctx, |ui| {
ui.heading("notes");
ui.label("the simple note taking app that uses encryption by default");
ui.separator();
ui.label("you need to put your password to access the notes");
ui.label(RichText::new("after starting the app, the password will be tested against the latest note").italics());
ui.add_space(10.0);
TextEdit::singleline(&mut self.password_buffer).password(true).ui(ui);
ui.add_space(7.5);
if ui.button("start app").clicked() {
self.password = Some(self.password_buffer.clone());
self.password_buffer = String::new();
self.mode = CurrentMode::View;
}
});
}
}
}
}