Skip to content

Commit

Permalink
Merge pull request #6 from tadghh/settings_revamp
Browse files Browse the repository at this point in the history
Settings revamp
  • Loading branch information
tadghh authored Sep 18, 2023
2 parents 6a79e1c + 4e3a7e0 commit df65714
Show file tree
Hide file tree
Showing 7 changed files with 76 additions and 101 deletions.
8 changes: 5 additions & 3 deletions components/settings/settings-item.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ export default function SettingsItem({
invoke("change_configuration_option", {
option_name: settingsConfigString,
value: value + "",
}).then(setSettingsItemStatus(value += ""));
}).then(setSettingsItemStatus((value += "")));
};

useEffect(() => {
Expand All @@ -31,7 +31,7 @@ export default function SettingsItem({
}, []);

return settingsItemStatus != "" ? (
<div className="flex items-center justify-between w-full p-4 mt-2 bg-white border h-28 rounded-xl">
<div className="mt-2 flex h-28 w-full items-center justify-between rounded-xl border bg-white p-4">
<div className="flex text-gray-900 ">
<h2 className="pr-2 text-2xl font-bold leading-4 ">{settingsTitle}</h2>
<p> {settingsDescription}</p>
Expand All @@ -45,5 +45,7 @@ export default function SettingsItem({
)}
</form>
</div>
) : <></>;
) : (
<></>
);
}
5 changes: 4 additions & 1 deletion pages/settings/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down Expand Up @@ -39,7 +40,9 @@ export default function Settings() {
<button
className=" rounded-lg bg-red-700 px-5 py-2.5 text-sm font-medium text-white hover:bg-red-800 focus:outline-none focus:ring-4 focus:ring-red-300 dark:bg-red-600 dark:hover:bg-red-700 dark:focus:ring-red-900"
type="button"
onClick={() => invoke("reset_configuration")}
onClick={() => {
invoke("reset_configuration");
}}
>
Reset settings
</button>
Expand Down
3 changes: 2 additions & 1 deletion src-tauri/src/book.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -64,6 +64,7 @@ pub fn load_book(title: String) -> Option<Book> {

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());
Expand Down
39 changes: 8 additions & 31 deletions src-tauri/src/book/bookio/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
///
Expand All @@ -40,31 +39,7 @@ pub fn write_cover_image(data: Option<(Vec<u8>, 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
Expand Down Expand Up @@ -114,8 +89,8 @@ pub fn initialize_books() -> Option<Vec<Book>> {
.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;
Expand Down Expand Up @@ -156,12 +131,14 @@ pub fn initialize_books() -> Option<Vec<Book>> {
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 {
Expand Down Expand Up @@ -190,9 +167,9 @@ pub fn initialize_books() -> Option<Vec<Book>> {
}
} 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");

Expand Down
3 changes: 1 addition & 2 deletions src-tauri/src/book/util/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
2 changes: 1 addition & 1 deletion src-tauri/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,5 +34,5 @@ fn main() {
]
)
.run(tauri::generate_context!())
.expect("error while running tauri application");
.expect("shelf seems to have fallen over");
}
117 changes: 55 additions & 62 deletions src-tauri/src/shelf.rs
Original file line number Diff line number Diff line change
@@ -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";
Expand All @@ -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<String, String> {
//Lower case the strings?
let setting_consts = ["BOOK_LOCATION","ENDLESS_SCROLL","COVER_BACKGROUND"];
// let shelf_option_values: HashMap<String, String> = 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<String, String> = setting_consts
.iter()
.map(|entry| (entry.to_string(), entry.to_lowercase()))
Expand All @@ -50,47 +45,60 @@ pub fn shelf_settings_values() -> HashMap<String, String> {
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
Expand All @@ -100,28 +108,11 @@ fn load_settings_into_memory( ) {
#[tauri::command(rename_all = "snake_case")]
pub fn get_configuration_option(option_name: String) -> Option<String> {
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
Expand All @@ -131,14 +122,13 @@ pub fn get_configuration_option(option_name: String) -> Option<String> {
/// * `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)
Expand All @@ -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;

Expand Down Expand Up @@ -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());
Expand All @@ -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(())
Expand Down

0 comments on commit df65714

Please sign in to comment.