Add basic project state and book listing

This commit is contained in:
Jarrod Doyle 2024-02-05 16:33:09 +00:00
parent f874cef96d
commit 136684ed74
Signed by: Jayrude
GPG Key ID: 38B57B16E7C0ADF7
6 changed files with 72 additions and 7 deletions

1
Cargo.lock generated
View File

@ -2368,6 +2368,7 @@ dependencies = [
"iced",
"rfd",
"tokio",
"walkdir",
]
[[package]]

View File

@ -9,3 +9,4 @@ edition = "2021"
iced = { git = "https://github.com/iced-rs/iced.git", version = "0.12.0", features = ["tokio"] }
rfd = "0.13.0"
tokio = { version = "1.35.1", features = ["fs"] }
walkdir = "2.4.0"

View File

@ -2,12 +2,13 @@ use std::{path::PathBuf, sync::Arc};
use iced::{
executor,
widget::{button, column, row, text, text_editor},
Application, Command, Element, Theme,
widget::{button, column, row, scrollable, text, text_editor, vertical_rule, Column},
Application, Command, Element, Length, Theme,
};
use crate::{
file::{default_file, load_file, pick_file},
file::{default_file, load_file, load_folder},
project::ProjectState,
Error,
};
@ -16,9 +17,11 @@ pub enum Message {
Open,
Edit(text_editor::Action),
FileOpened(Result<(PathBuf, Arc<String>), Error>),
FolderSelected(Result<PathBuf, Error>),
}
pub struct BookManagerApp {
project: Option<ProjectState>,
book_path: Option<PathBuf>,
book_content: text_editor::Content,
io_error: Option<Error>,
@ -33,6 +36,7 @@ impl Application for BookManagerApp {
fn new(_flags: Self::Flags) -> (Self, Command<Self::Message>) {
(
Self {
project: None,
book_path: None,
book_content: text_editor::Content::new(),
io_error: None,
@ -55,8 +59,12 @@ impl Application for BookManagerApp {
}
Err(error) => self.io_error = Some(error),
},
Message::FolderSelected(result) => match result {
Ok(path) => self.project = Some(ProjectState::new(path)),
Err(error) => self.io_error = Some(error),
},
Message::Open => {
return Command::perform(pick_file(), Message::FileOpened);
return Command::perform(load_folder(), Message::FolderSelected);
}
}
@ -68,10 +76,19 @@ impl Application for BookManagerApp {
let controls = row![button("Open").on_press(Message::Open)];
let active_editor = text_editor(&self.book_content).on_action(Message::Edit);
column![hello_world, controls, active_editor]
let mut books: Vec<Element<'_, Self::Message>> = vec![];
if let Some(project) = &self.project {
for book in project.books.iter() {
books.push(text(book.file_name.clone()).into());
}
}
let left_panel = scrollable(Column::with_children(books)).width(Length::Fixed(256.0));
let right_panel = column![hello_world, controls, active_editor]
.spacing(10)
.padding(10)
.into()
.padding(10);
row![left_panel, vertical_rule(2), right_panel].into()
}
fn theme(&self) -> Theme {

View File

@ -23,3 +23,12 @@ pub async fn pick_file() -> Result<(PathBuf, Arc<String>), Error> {
pub fn default_file() -> PathBuf {
PathBuf::from(format!("{}/src/main.rs", env!("CARGO_MANIFEST_DIR")))
}
pub async fn load_folder() -> Result<PathBuf, Error> {
let file_handle = rfd::AsyncFileDialog::new()
.set_title("Choose project folder...")
.pick_folder()
.await
.ok_or(Error::DialogClosed)?;
Ok(file_handle.path().to_owned())
}

View File

@ -1,5 +1,6 @@
mod application;
mod file;
mod project;
use std::io;

36
src/project.rs Normal file
View File

@ -0,0 +1,36 @@
use std::{ffi::OsStr, path::PathBuf};
use walkdir::WalkDir;
#[derive(Debug, Clone)]
pub struct Book {
pub path: PathBuf,
pub file_name: String,
}
#[derive(Debug, Clone)]
pub struct ProjectState {
pub path: PathBuf,
pub books: Vec<Book>,
}
impl ProjectState {
pub fn new(path: PathBuf) -> Self {
let mut books = vec![];
let book_walker = WalkDir::new(path.join("books")).into_iter();
for entry in book_walker.flatten() {
if entry.metadata().is_ok_and(|md| md.is_dir()) {
continue;
}
let extension = entry.path().extension().and_then(OsStr::to_str);
if extension.is_some_and(|ext| ext.to_lowercase() == "str") {
books.push(Book {
path: entry.path().to_owned(),
file_name: entry.file_name().to_str().unwrap().to_owned(),
});
}
}
Self { path, books }
}
}