diff --git a/components/settings/settings-item.js b/components/settings/settings-item.js index 933a329..45d9bb0 100644 --- a/components/settings/settings-item.js +++ b/components/settings/settings-item.js @@ -17,7 +17,7 @@ export default function SettingsItem({ invoke("change_configuration_option", { option_name: settingsConfigString, value: value + "", - }).then(setSettingsItemStatus(value += "")); + }).then(setSettingsItemStatus((value += ""))); }; useEffect(() => { @@ -31,7 +31,7 @@ export default function SettingsItem({ }, []); return settingsItemStatus != "" ? ( -
+

{settingsTitle}

{settingsDescription}

@@ -45,5 +45,7 @@ export default function SettingsItem({ )}
- ) : <>; + ) : ( + <> + ); } diff --git a/pages/settings/index.js b/pages/settings/index.js index 37b3ebb..89dd42b 100644 --- a/pages/settings/index.js +++ b/pages/settings/index.js @@ -9,6 +9,7 @@ export default function Settings() { const [settingsItemsEnum, setSettingsItemsEnum] = useState(null); useEffect(() => { async function loadEnum() { + console.log(await SettingsItems()); setSettingsItemsEnum(await SettingsItems()); } loadEnum(); @@ -39,7 +40,9 @@ export default function Settings() { diff --git a/src-tauri/src/book.rs b/src-tauri/src/book.rs index 3c7cde1..8201907 100644 --- a/src-tauri/src/book.rs +++ b/src-tauri/src/book.rs @@ -4,7 +4,7 @@ use epub::doc::EpubDoc; use regex::Regex; use xmltree::Element; -use crate::book::util::{ chunk_binary_search_index_load, base64_encode_file, check_epub_resource }; +use crate::book::util::{ chunk_binary_search_index_load, check_epub_resource }; use crate::xml::extract_image_source; use self::bookio::write_cover_image; @@ -64,6 +64,7 @@ pub fn load_book(title: String) -> Option { let books = &BOOK_JSON.books; let book_index = chunk_binary_search_index_load(books, &title); + if let Some(book) = books.get(book_index.unwrap()) { // Accessing the book at the specified index return Some(book.clone()); diff --git a/src-tauri/src/book/bookio/mod.rs b/src-tauri/src/book/bookio/mod.rs index e7b9f68..8ca5c4a 100644 --- a/src-tauri/src/book/bookio/mod.rs +++ b/src-tauri/src/book/bookio/mod.rs @@ -10,10 +10,9 @@ use std::{ use rayon::prelude::{ IntoParallelRefIterator, ParallelIterator }; use crate::{ book::{ util::{ chunk_binary_search_index, get_cache_dir }, BOOK_JSON, Book, create_cover }, - shelf::{ get_cache_file_name, get_configuration_option, get_settings_name }, + shelf::{ get_cache_file_name, get_configuration_option }, }; -use super::util::get_config_dir; /// Writes the cover image to the specified path /// @@ -40,31 +39,7 @@ pub fn write_cover_image(data: Option<(Vec, String)>, path: &PathBuf) -> Res Ok(()) } -/// Creates the default settings file if none exists -pub fn create_default_settings_file() { - let settings_path = get_config_dir().join(get_settings_name()); - print!("{:?}", get_config_dir().join(get_settings_name())); - // Check if the file already exists - if fs::metadata(&settings_path).is_err() { - // File doesn't exist, create a new one with default values - let default_settings = - r#" - book_location=None - endless_scroll=false - "#; - - let mut file = OpenOptions::new() - .create(true) - .write(true) - .truncate(true) - .open(&settings_path) - .expect("Failed to create settings file"); - - file.write_all(default_settings.as_bytes()).expect( - "Failed to write default settings to file" - ); - } -} + /// Creates a vector containing all the books and returns a a vector of book objects, here we also create the covers /// The returned json is sorted alphabetically so we can use binary sort when there are a large number of books @@ -114,8 +89,8 @@ pub fn initialize_books() -> Option> { .to_string_lossy() .to_string() .clone(); - println!("Its here {}", json_path); - let dir = match get_configuration_option("book_location".to_string()) { + + let dir = match get_configuration_option("book_location".to_string()) { Some(val) => val, None => { return None; @@ -156,12 +131,14 @@ pub fn initialize_books() -> Option> { if current_length != &epubs.len() { let book_json_len = Arc::new(AtomicUsize::new(book_json.len())); let book_json_test = Arc::new(Mutex::new(book_json)); - println!("Diff size"); + epubs.par_iter().for_each(|item| { let item_normalized = item.replace('\\', "/"); let title = EpubDoc::new(&item_normalized).unwrap().mdata("title").unwrap(); let mut book_json_guard = book_json_test.lock().unwrap(); let index = chunk_binary_search_index(&book_json_guard, &title); + + //TODO: Duplicated code? match index { Some(index) => { let new_book = Book { @@ -190,9 +167,9 @@ pub fn initialize_books() -> Option> { } } else { book_json = create_book_vec(&epubs, covers_directory); - println!("{} length", book_json.len()); file_changes = true; } + if file_changes { let file = File::create(json_path).expect("JSON path should be defined, and a valid path"); diff --git a/src-tauri/src/book/util/mod.rs b/src-tauri/src/book/util/mod.rs index 05db545..ee980d8 100644 --- a/src-tauri/src/book/util/mod.rs +++ b/src-tauri/src/book/util/mod.rs @@ -32,17 +32,16 @@ pub fn sanitize_windows_filename(filename: String) -> String { pub fn get_config_dir() -> PathBuf { let mut full_config_path = config_dir().expect("Failed to get config directory"); full_config_path.push("shelf\\config"); // Use forward slashes - println!("Path: {:?}", full_config_path.to_str().unwrap()); if let Err(err) = fs::create_dir_all(&full_config_path) { eprintln!("Error creating cache directory: {:?}", err); } + full_config_path } pub fn get_cache_dir() -> PathBuf { let mut cache_dir = cache_dir().expect("Failed to get cache directory"); cache_dir.push("shelf\\covers"); // Use forward slashes - println!("Path: {:?}", cache_dir.to_str().unwrap()); if let Err(err) = fs::create_dir_all(&cache_dir) { eprintln!("Error creating cache directory: {:?}", err); diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs index 94523e4..235b4d2 100644 --- a/src-tauri/src/main.rs +++ b/src-tauri/src/main.rs @@ -34,5 +34,5 @@ fn main() { ] ) .run(tauri::generate_context!()) - .expect("error while running tauri application"); + .expect("shelf seems to have fallen over"); } diff --git a/src-tauri/src/shelf.rs b/src-tauri/src/shelf.rs index d41d9e5..c604841 100644 --- a/src-tauri/src/shelf.rs +++ b/src-tauri/src/shelf.rs @@ -1,11 +1,11 @@ use std::{ collections::HashMap, - fs::{OpenOptions, File, remove_file, remove_dir_all}, + fs::{OpenOptions, remove_file, remove_dir_all}, io::{ BufRead, BufReader, Seek, SeekFrom, Write, Read }, path::PathBuf, }; -use crate::book::{ bookio::create_default_settings_file, util::{get_config_dir, get_cache_dir} }; +use crate::book::util::{get_config_dir, get_cache_dir}; static CACHE_FILE_NAME: &str = "book_cache.json"; static SETTINGS_FILE_NAME: &str = "shelf_settings.conf"; @@ -31,17 +31,12 @@ pub fn get_settings_name() -> &'static str { SETTINGS_FILE_NAME } -///I have enums I want to use in the front end so this is how we get the -///Hardcoding bad ya ya ya... +///This is how we get out settings back over to nextjs. +///TODO: Use enums throughout backend, lazy guy :| #[tauri::command] pub fn shelf_settings_values() -> HashMap { - //Lower case the strings? let setting_consts = ["BOOK_LOCATION","ENDLESS_SCROLL","COVER_BACKGROUND"]; - // let shelf_option_values: HashMap = HashMap::from([ - // ("BOOK_LOCATION".to_string(), "book_folder_location".to_string()), - // ("ENDLESS_SCROLL".to_string(), "endless_scroll".to_string()), - // ("COVER_BACKGROUND".to_string(), "COVER_BACKGROUND".to_string()), - // ]); + let shelf_option_values: HashMap = setting_consts .iter() .map(|entry| (entry.to_string(), entry.to_lowercase())) @@ -50,47 +45,60 @@ pub fn shelf_settings_values() -> HashMap { shelf_option_values } +/// To force overwrite users settings in memory fn load_settings(){ let settings_path = get_settings_path(); - let file = match - OpenOptions::new().read(true).write(true).create(true).open(&settings_path) - { - Ok(file) => file, - Err(e) => { - eprintln!("Error opening settings file, trying to create one: {}", e); - create_default_settings_file(); - OpenOptions::new() - .read(true) - .write(true) - .open(&settings_path) - .expect("Failed to open settings file") - } - }; + let file = match + OpenOptions::new().read(true).write(true).create(true).open(&settings_path) + { + Ok(file) => file, + Err(e) => { + eprintln!("Error opening settings file, trying to create one: {}", e); + restore_default_settings(); + OpenOptions::new() + .read(true) + .write(true) + .open(&settings_path) + .expect("Failed to open settings file") + } + }; - let reader = BufReader::new(&file); + let reader = BufReader::new(&file); - let mut settings_map = HashMap::new(); - for line in reader.lines() { - let line_content = line.unwrap(); - let split: Vec<&str> = line_content.split('=').collect(); - if split.len() == 2 { - settings_map.insert(split[0].to_string(), split[1].to_string()); - } - } + let mut settings_map = HashMap::new(); - unsafe { SETTINGS_MAP = Some(settings_map) }; + for line in reader.lines() { + let line_content = line.unwrap(); + let split: Vec<&str> = line_content.split('=').collect(); + + if split.len() == 2 { + settings_map.insert(split[0].to_string(), split[1].to_string()); + } + } + + unsafe { SETTINGS_MAP = Some(settings_map) }; } -///Just to messing around, looking for more performant solutions -fn load_settings_into_memory( ) { +///Load user settings into memory, if they havent already been +fn load_settings_into_memory() { unsafe { if SETTINGS_MAP.is_none() { - - load_settings() + load_settings(); } } } + +/// Sets all settings consts to be "unset" or default +pub fn restore_default_settings() { + load_settings_into_memory(); + + //TODO: Unset is not a "good" default value + for entry in shelf_settings_values().iter() { + change_configuration_option(entry.1.to_owned(), "Unset".to_string()); + } +} + /// Returns the setting for the provided value /// /// # Arguments @@ -100,28 +108,11 @@ fn load_settings_into_memory( ) { #[tauri::command(rename_all = "snake_case")] pub fn get_configuration_option(option_name: String) -> Option { load_settings_into_memory(); - let value = unsafe { SETTINGS_MAP.as_ref().and_then(|map| map.get(&option_name).cloned()) }; - - if value.is_none() { - // Option not found, call change_configuration_option and check if it was successful - change_configuration_option(option_name.clone(), "Unset".to_string()); - - // Recheck the value after attempting to change the option - unsafe { - if - let Some(updated_value) = SETTINGS_MAP.as_ref().and_then(|map| - map.get(&option_name).cloned() - ) - { - return Some(updated_value); - } else { - eprintln!("Failed to set option: {}", option_name); - return None; - } - } - } - value + //TODO: Could encounter error if memory issue + let settings_value = unsafe { SETTINGS_MAP.as_ref().and_then(|map| map.get(&option_name).cloned()) }; + + settings_value } /// Changes the value of a settings item @@ -131,14 +122,13 @@ pub fn get_configuration_option(option_name: String) -> Option { /// * `option_name` - The setting to change /// * `value` - The new value to set /// -/// #[tauri::command(rename_all = "snake_case")] pub fn change_configuration_option(option_name: String, value: String) { load_settings_into_memory(); unsafe { if let Some(map) = &mut SETTINGS_MAP { map.insert(option_name.clone(), value.clone()); - // let settings_path = format!("{}/{}", home_dir, &SETTINGS_FILE_NAME); + let settings_path = get_settings_path(); let mut file = OpenOptions::new() .create(true) @@ -149,6 +139,7 @@ pub fn change_configuration_option(option_name: String, value: String) { let mut contents = String::new(); file.read_to_string(&mut contents).unwrap(); + if let Some(index) = contents.find(&format!("{}=", option_name)) { let start = index + option_name.len() + 1; @@ -189,6 +180,7 @@ pub fn change_configuration_option(option_name: String, value: String) { #[tauri::command(rename_all = "snake_case")] pub fn reset_configuration() -> Result<(), String>{ + //TODO: Handle these errors on front end, let user know it didnt work //Delete book json and covers if let Err(err) = remove_dir_all(get_cache_dir()) { return Err(err.to_string()); @@ -198,8 +190,9 @@ pub fn reset_configuration() -> Result<(), String>{ if let Err(err) = remove_file(get_settings_path()) { return Err(err.to_string()); } + //call default settings - create_default_settings_file(); + restore_default_settings(); load_settings(); Ok(())