From d60f002ba56e851c05b3b277db2df48a557f1c76 Mon Sep 17 00:00:00 2001 From: Travis Lane <63308171+Tormak9970@users.noreply.github.com> Date: Fri, 15 Nov 2024 11:48:34 -0500 Subject: [PATCH 1/2] chore: organized rust code --- src-tauri/src/clean_grids.rs | 103 ++++ src-tauri/src/handle_changes.rs | 257 +++++++++ src-tauri/src/main.rs | 497 +----------------- .../src/{ => parsers}/appinfo_vdf_parser.rs | 2 +- src-tauri/src/parsers/mod.rs | 4 + .../src/{ => parsers}/shortcuts_vdf_parser.rs | 2 +- src-tauri/src/{ => parsers}/vdf_reader.rs | 0 src-tauri/src/{ => parsers}/vdf_structs.rs | 0 src-tauri/src/steam.rs | 67 ++- src-tauri/src/{ => utils}/logger.rs | 0 src-tauri/src/utils/mod.rs | 3 + src-tauri/src/{ => utils}/reader.rs | 0 src-tauri/src/{ => utils}/writer.rs | 0 src-tauri/src/zip_controller.rs | 116 +++- 14 files changed, 543 insertions(+), 508 deletions(-) create mode 100644 src-tauri/src/clean_grids.rs create mode 100644 src-tauri/src/handle_changes.rs rename src-tauri/src/{ => parsers}/appinfo_vdf_parser.rs (99%) create mode 100644 src-tauri/src/parsers/mod.rs rename src-tauri/src/{ => parsers}/shortcuts_vdf_parser.rs (98%) rename src-tauri/src/{ => parsers}/vdf_reader.rs (100%) rename src-tauri/src/{ => parsers}/vdf_structs.rs (100%) rename src-tauri/src/{ => utils}/logger.rs (100%) create mode 100644 src-tauri/src/utils/mod.rs rename src-tauri/src/{ => utils}/reader.rs (100%) rename src-tauri/src/{ => utils}/writer.rs (100%) diff --git a/src-tauri/src/clean_grids.rs b/src-tauri/src/clean_grids.rs new file mode 100644 index 00000000..c042ae6d --- /dev/null +++ b/src-tauri/src/clean_grids.rs @@ -0,0 +1,103 @@ +use std::{collections::HashMap, fs, path::PathBuf}; + +use tauri::AppHandle; + +use crate::{steam, utils::logger, zip_controller}; + + +#[derive(Clone, serde::Serialize)] +#[allow(non_snake_case)] +struct CleanConflicts { + fileAName: String, + fileAPath: String, + fileBName: String, + fileBPath: String, + appid: String, + gridType: String +} + +#[tauri::command] +/// Downloads a file from a url. +pub async fn clean_grids(app_handle: AppHandle, steam_path: String, steam_active_user_id: String, preset: String, all_appids: String, selected_game_ids: String) -> String { + logger::log_to_core_file(app_handle.to_owned(), format!("Starting {} grid cleaning.", preset).as_str(), 0); + + let appids_arr: Vec = serde_json::from_str(all_appids.as_str()).expect("Should have been able to deserialize appids array."); + + let grids_dir_path: String = steam::get_grids_directory(app_handle.to_owned(), steam_path, steam_active_user_id); + let grids_dir_contents = fs::read_dir(grids_dir_path).unwrap(); + + let mut found_apps: HashMap = HashMap::new(); + let mut conflicts: Vec = Vec::new(); + + + if preset == String::from("clean") { + for dir_entry in grids_dir_contents { + let entry = dir_entry.expect("Should have been able to get directory entry."); + + if !entry.file_type().unwrap().is_file() { + continue; + } + + let full_file_path: PathBuf = entry.path(); + let full_file_path_str: &str = full_file_path.to_str().unwrap(); + let filename = entry.file_name(); + let filename_str: &str = filename.to_str().unwrap(); + + let (id, grid_type) = zip_controller::get_id_from_grid_name(filename_str); + let id_type_str: String = format!("{}_{}", id, grid_type); + + if !appids_arr.contains(&id) { + let remove_res = fs::remove_file(full_file_path); + if remove_res.is_err() { + let err = remove_res.err().unwrap(); + return format!("{{ \"error\": \"{}\"}}", err.to_string()); + } + + logger::log_to_core_file(app_handle.to_owned(), format!("Deleted {}.", filename_str).as_str(), 0); + continue; + } + + if found_apps.contains_key(&id_type_str) { + // ? There's a conflict + let (other_filename, other_full_path) = found_apps.get(&id_type_str).expect("Map should have contained the id_type_str."); + + conflicts.push(CleanConflicts { fileAPath: other_full_path.to_owned(), fileAName: other_filename.to_owned(), fileBPath: String::from(full_file_path_str), fileBName: String::from(filename_str), appid: id.clone(), gridType: grid_type.clone() }); + + logger::log_to_core_file(app_handle.to_owned(), format!("Detected conflict between {} and {}.", filename_str, other_filename).as_str(), 0); + } else { + found_apps.insert(id_type_str, (String::from(filename_str), String::from(full_file_path_str))); + } + } + } else { + let game_ids_arr: Vec = serde_json::from_str(selected_game_ids.as_str()).expect("Should have been able to deserialize selected appids array."); + + for dir_entry in grids_dir_contents { + let entry = dir_entry.expect("Should have been able to get directory entry."); + + if !entry.file_type().unwrap().is_file() { + continue; + } + + let full_file_path: PathBuf = entry.path(); + let filename = entry.file_name(); + let filename_str: &str = filename.to_str().unwrap(); + + let (id, _) = zip_controller::get_id_from_grid_name(filename_str); + + if game_ids_arr.contains(&id) { + let remove_res = fs::remove_file(full_file_path); + if remove_res.is_err() { + let err = remove_res.err().unwrap(); + return format!("{{ \"error\": \"{}\"}}", err.to_string()); + } + + logger::log_to_core_file(app_handle.to_owned(), format!("Deleted {}.", filename_str).as_str(), 0); + } + } + } + + + logger::log_to_core_file(app_handle.to_owned(), format!("{} grid cleaning complete.", preset).as_str(), 0); + + return serde_json::to_string(&conflicts).expect("Should have been able to serialize conflict array."); +} diff --git a/src-tauri/src/handle_changes.rs b/src-tauri/src/handle_changes.rs new file mode 100644 index 00000000..b5c9e379 --- /dev/null +++ b/src-tauri/src/handle_changes.rs @@ -0,0 +1,257 @@ +use std::{path::PathBuf, collections::HashMap, fs}; + +use crate::parsers::shortcuts_vdf_parser::write_shortcuts_vdf; +use serde_json::{Map, Value}; + +use serde; +use crate::steam; +use tauri::{self, AppHandle}; + +use crate::logger; + +type GridImageCache = HashMap>; + +#[derive(serde::Serialize, serde::Deserialize, Debug, PartialEq, Clone)] +#[allow(non_snake_case)] +struct ChangedPath { + appId: String, + gridType: String, + oldPath: String, + targetPath: String, + sourcePath: String +} + +/// Checks if an appid belongs to a shortcut +fn is_appid_shortcut(appid: &str, shortcut_icons: &Map) -> bool { + return shortcut_icons.contains_key(appid); +} + +/// Gets a grid's file name based on its type. +fn get_grid_filename(app_handle: &AppHandle, appid: &str, grid_type: &str, image_type: &str) -> String { + match grid_type { + "Capsule" => return format!("{}p{}", appid, image_type), + "Wide Capsule" => return format!("{}{}", appid, image_type), + "Hero" => return format!("{}_hero{}", appid, image_type), + "Logo" => return format!("{}_logo{}", appid, image_type), + "Icon" => return format!("{}_icon.jpg", appid), + _ => { + logger::log_to_core_file(app_handle.to_owned(), format!("Unexpected grid type {}", grid_type).as_str(), 2); + panic!("Unexpected grid type {}", grid_type); + } + } +} + +/// Adjusts the path of a grid based on its type. +fn adjust_path(app_handle: &AppHandle, appid: &str, path: &str, grid_type: &str) -> String { + let format_start_index = path.rfind(".").expect("Path should have had a file extension."); + let image_type = &path[format_start_index..]; + return get_grid_filename(app_handle, appid, grid_type, image_type); +} + +/// Filters the grid paths based on which have change. +fn filter_paths(app_handle: &AppHandle, steam_path: String, steam_active_user_id: String, current_paths: &GridImageCache, original_paths: &GridImageCache, shortcut_icons: &Map) -> Vec { + let grids_dir = PathBuf::from(steam::get_grids_directory(app_handle.to_owned(), steam_path.to_owned(), steam_active_user_id)); + let lib_cache_dir = PathBuf::from(steam::get_library_cache_directory(app_handle.to_owned(), steam_path.to_owned())); + let mut res:Vec = Vec::new(); + + for (appid, grids_map) in current_paths.into_iter() { + for (grid_type, source_path) in grids_map.into_iter() { + let mut grid_path: &String = &String::from(""); + + if original_paths.get(appid.as_str()).is_some() && original_paths.get(appid.as_str()).unwrap().get(grid_type.as_str()).is_some() { + grid_path = original_paths.get(appid.as_str()).unwrap().get(grid_type.as_str()).unwrap(); + } + + let grid_path_owned = grid_path.to_owned(); + let source_path_owned = source_path.to_owned(); + + if source_path_owned != grid_path_owned { + let target_path; + + if source_path != "REMOVE" { + let adjusted_path = adjust_path(app_handle, appid.as_str(), source_path_owned.as_str(), grid_type.as_str()).replace("\\", "/"); + if grid_type == "Icon" && !is_appid_shortcut(&appid, shortcut_icons) { + target_path = String::from(lib_cache_dir.join(adjusted_path).to_str().unwrap()).replace("\\", "/"); + } else { + target_path = String::from(grids_dir.join(adjusted_path).to_str().unwrap()).replace("\\", "/"); + } + } else { + target_path = String::from("REMOVE"); + } + + let mut changed_path = ChangedPath { + appId: appid.to_owned(), + gridType: grid_type.to_owned(), + oldPath: grid_path_owned.replace("\\", "/"), + targetPath: target_path.to_owned(), + sourcePath: source_path_owned.replace("\\", "/") + }; + + if changed_path.targetPath.ends_with(".webp") { + let target: String = changed_path.targetPath; + let mut jpg_target: String = target[..target.len() - 5].to_owned(); + jpg_target.push_str(".jpg"); + + changed_path.targetPath = String::from(jpg_target.to_owned()); + } + + res.push(changed_path); + } + } + } + + return res; +} + +/// Checks for shortcut grid changes. +fn check_for_shortcut_changes(shortcut_icons: &Map, original_shortcut_icons: &Map) -> bool { + for (shortcut_id, icon) in shortcut_icons.to_owned().into_iter() { + let icon: &str = icon.as_str().expect("Should have been able to convert icon to &str."); + let original_icon: &str = original_shortcut_icons.get(&shortcut_id).expect("Original hortcut should have had an icon.").as_str().expect("Should have been able to convert original icon to &str."); + + if icon != original_icon { + return true; + } + } + + return false; +} + + + +#[tauri::command] +/// Applies the changes the user has made. +pub async fn save_changes(app_handle: AppHandle, steam_path: String, steam_active_user_id: String, current_art: String, original_art: String, shortcuts_str: String, shortcut_icons: Map, original_shortcut_icons: Map, changed_logo_positions: Map) -> String { + let current_art_dict: GridImageCache = serde_json::from_str(current_art.as_str()).unwrap(); + let original_art_dict: GridImageCache = serde_json::from_str(original_art.as_str()).unwrap(); + + logger::log_to_core_file(app_handle.to_owned(), "Converting current path entries to grid paths...", 0); + let paths_to_set: Vec = filter_paths(&app_handle, steam_path.to_owned(), steam_active_user_id.clone(), ¤t_art_dict, &original_art_dict, &shortcut_icons); + let paths_id_map: HashMap = paths_to_set.clone().iter().map(| entry | (format!("{}_{}", entry.appId.to_owned(), entry.gridType.to_owned()).to_string(), entry.to_owned())).collect(); + logger::log_to_core_file(app_handle.to_owned(), "Current path entries converted to grid paths.", 0); + + for changed_path in (&paths_to_set).into_iter() { + let source = changed_path.sourcePath.to_owned(); + let target = changed_path.targetPath.to_owned(); + + if target == String::from("REMOVE") { + if changed_path.oldPath.contains("grid") { + let remove_res = fs::remove_file(changed_path.oldPath.to_owned()); + if remove_res.is_err() { + let err = remove_res.err().unwrap(); + return format!("{{ \"error\": \"{}\"}}", err.to_string()); + } + + logger::log_to_core_file(app_handle.to_owned(), format!("Removed grid {}.", changed_path.oldPath.to_owned()).as_str(), 0); + } + } else { + if changed_path.oldPath.contains("grid") { + let remove_res = fs::remove_file(changed_path.oldPath.to_owned()); + if remove_res.is_err() { + let err = remove_res.err().unwrap(); + return format!("{{ \"error\": \"{}\"}}", err.to_string()); + } + } + + fs::File::create(target.clone()).unwrap(); + + let copy_res = fs::copy(source.clone(), target.clone()); + + if copy_res.is_err() { + logger::log_to_core_file(app_handle.to_owned(), format!("Failed to copy {} to {}.", source, target).as_str(), 2); + let err = copy_res.err().unwrap(); + return format!("{{ \"error\": \"{}\"}}", err.to_string()); + } + + logger::log_to_core_file(app_handle.to_owned(), format!("Copied {} to {}.", source, target).as_str(), 0); + } + } + + let grids_directory: PathBuf = PathBuf::from(steam::get_grids_directory(app_handle.to_owned(), steam_path.to_owned(), steam_active_user_id.clone())); + for (appid, steam_logo_str_val) in changed_logo_positions.into_iter() { + let steam_logo_str: &str = steam_logo_str_val.as_str().expect("Should have been able to convert steamLogo pos into str."); + let logo_config_path: PathBuf = grids_directory.join(format!("{}.json", appid)); + + if steam_logo_str == "REMOVE" { + let remove_res = fs::remove_file(logo_config_path); + if remove_res.is_err() { + let err = remove_res.err().unwrap(); + return format!("{{ \"error\": \"{}\"}}", err.to_string()); + } + + logger::log_to_core_file(app_handle.to_owned(), format!("Removed logo position config for {}.", appid).as_str(), 0); + } else { + let write_res = fs::write(&logo_config_path, steam_logo_str); + + if write_res.is_err() { + logger::log_to_core_file(app_handle.to_owned(), format!("Failed to write logo pos to config for {}.", appid).as_str(), 2); + let err = write_res.err().unwrap(); + return format!("{{ \"error\": \"{}\"}}", err.to_string()); + } + + logger::log_to_core_file(app_handle.to_owned(), format!("Wrote logo pos to config for {}.", appid).as_str(), 0); + } + } + + let should_change_shortcuts: bool = check_for_shortcut_changes(&shortcut_icons, &original_shortcut_icons); + + if should_change_shortcuts { + logger::log_to_core_file(app_handle.to_owned(), "Changes to shortcuts detected. Writing shortcuts.vdf...", 0); + let mut shortcuts_data: Value = serde_json::from_str(shortcuts_str.as_str()).expect("Should have been able to parse json string."); + + let shortcuts_obj_map: &mut Value = shortcuts_data.get_mut("shortcuts").expect("key: shortcuts should have existed."); + let shortcuts_map: &mut Map = shortcuts_obj_map.as_object_mut().expect("Should have been able to convert shortcuts to map"); + + for (_, shortcut) in shortcuts_map.into_iter() { + let shortcut_map: &mut Map = shortcut.as_object_mut().expect("should have been able to convert shortcut to map."); + let shortcut_appid_val: &Value = shortcut_map.get("appid").expect("shortcut should have had an appid"); + let shortcut_appid_num: i64 = shortcut_appid_val.as_i64().expect("should have been able to convert shortcut appid to str."); + let shortcut_appid: String = shortcut_appid_num.to_string(); + + let path_key: String = format!("{}_icon", shortcut_appid.to_owned()).to_string(); + + if paths_id_map.contains_key(&path_key) { + let changed_path: &ChangedPath = paths_id_map.get(&path_key).expect("entry should have existed."); + shortcut_map.insert(String::from("icon"), Value::String(changed_path.targetPath.to_owned())); + } + } + + let mut modified_shortcuts_data: Map = Map::new(); + modified_shortcuts_data.insert(String::from("shortcuts"), shortcuts_obj_map.to_owned()); + shortcuts_data = Value::Object(modified_shortcuts_data); + + let shortcuts_vdf_path: PathBuf = PathBuf::from(steam::get_shortcuts_path(app_handle.to_owned(), steam_path.to_owned(), steam_active_user_id)); + write_shortcuts_vdf(&shortcuts_vdf_path, shortcuts_data); + logger::log_to_core_file(app_handle.to_owned(), "Changes to shortcuts saved.", 0); + } else { + logger::log_to_core_file(app_handle.to_owned(), "No changes to shortcuts detected. Skipping...", 0); + } + + let changed_res = serde_json::to_string::>(paths_to_set.as_ref()); + + if changed_res.is_err() { + let err = changed_res.err().unwrap(); + logger::log_to_core_file(app_handle, format!("{}", err.to_string()).as_str(), 2); + return String::from("[]"); + } + + return changed_res.unwrap(); +} + +#[tauri::command] +/// Writes the user's shortcuts.vdf file. +pub async fn write_shortcuts(app_handle: AppHandle, steam_path: String, steam_active_user_id: String, shortcuts_str: String) -> bool { + logger::log_to_core_file(app_handle.to_owned(), "Writing shortcuts.vdf...", 0); + let shortcuts_vdf_path: PathBuf = PathBuf::from(steam::get_shortcuts_path(app_handle.to_owned(), steam_path, steam_active_user_id)); + let shortcuts_data: Value = serde_json::from_str(shortcuts_str.as_str()).expect("Should have been able to parse json string."); + + let success: bool = write_shortcuts_vdf(&shortcuts_vdf_path, shortcuts_data); + + if success { + logger::log_to_core_file(app_handle.to_owned(), "Changes to shortcuts saved.", 0); + return true; + } else { + logger::log_to_core_file(app_handle.to_owned(), "Changes to shortcuts failed.", 0); + return false; + } +} diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs index 069c725e..54e6604e 100644 --- a/src-tauri/src/main.rs +++ b/src-tauri/src/main.rs @@ -1,28 +1,19 @@ #![cfg_attr(not(debug_assertions), windows_subsystem = "windows")] -mod reader; -mod writer; -mod vdf_structs; -mod logger; +mod utils; +mod parsers; +mod handle_changes; mod steam; mod zip_controller; -mod appinfo_vdf_parser; -mod shortcuts_vdf_parser; -mod vdf_reader; mod start_menu_tiles; mod grids_cache_loader; +mod clean_grids; use tauri_plugin_dialog::DialogExt; use tauri_plugin_fs::FsExt; use tauri_plugin_http::reqwest::Client; -use std::{path::PathBuf, collections::HashMap, fs::{self, File}, io::Write, time::Duration, panic::{self, Location}, process::exit}; - -use appinfo_vdf_parser::open_appinfo_vdf; -use serde_json::{Map, Value}; -use shortcuts_vdf_parser::{open_shortcuts_vdf, write_shortcuts_vdf}; - -use home::home_dir; +use std::{path::PathBuf, fs::{self, File}, io::Write, time::Duration, panic::{self, Location}, process::exit}; use serde; use steam::get_steam_root_dir; @@ -30,390 +21,14 @@ use panic_message::get_panic_info_message; use tauri::{self, AppHandle, Manager}; use tauri::Emitter; +use utils::{logger, reader, writer}; + #[derive(Clone, serde::Serialize)] struct Payload { args: Vec, cwd: String, } -#[derive(Clone, serde::Serialize)] -#[allow(non_snake_case)] -struct CleanConflicts { - fileAName: String, - fileAPath: String, - fileBName: String, - fileBPath: String, - appid: String, - gridType: String -} - -type GridImageCache = HashMap>; - -#[derive(serde::Serialize, serde::Deserialize, Debug, PartialEq, Clone)] -#[allow(non_snake_case)] -struct ChangedPath { - appId: String, - gridType: String, - oldPath: String, - targetPath: String, - sourcePath: String -} - -/// Checks if an appid belongs to a shortcut -fn is_appid_shortcut(appid: &str, shortcut_icons: &Map) -> bool { - return shortcut_icons.contains_key(appid); -} - -/// Gets a grid's file name based on its type. -fn get_grid_filename(app_handle: &AppHandle, appid: &str, grid_type: &str, image_type: &str) -> String { - match grid_type { - "Capsule" => return format!("{}p{}", appid, image_type), - "Wide Capsule" => return format!("{}{}", appid, image_type), - "Hero" => return format!("{}_hero{}", appid, image_type), - "Logo" => return format!("{}_logo{}", appid, image_type), - "Icon" => return format!("{}_icon.jpg", appid), - _ => { - logger::log_to_core_file(app_handle.to_owned(), format!("Unexpected grid type {}", grid_type).as_str(), 2); - panic!("Unexpected grid type {}", grid_type); - } - } -} - -/// Adjusts the path of a grid based on its type. -fn adjust_path(app_handle: &AppHandle, appid: &str, path: &str, grid_type: &str) -> String { - let format_start_index = path.rfind(".").expect("Path should have had a file extension."); - let image_type = &path[format_start_index..]; - return get_grid_filename(app_handle, appid, grid_type, image_type); -} - -/// Filters the grid paths based on which have change. -fn filter_paths(app_handle: &AppHandle, steam_path: String, steam_active_user_id: String, current_paths: &GridImageCache, original_paths: &GridImageCache, shortcut_icons: &Map) -> Vec { - let grids_dir = PathBuf::from(steam::get_grids_directory(app_handle.to_owned(), steam_path.to_owned(), steam_active_user_id)); - let lib_cache_dir = PathBuf::from(steam::get_library_cache_directory(app_handle.to_owned(), steam_path.to_owned())); - let mut res:Vec = Vec::new(); - - for (appid, grids_map) in current_paths.into_iter() { - for (grid_type, source_path) in grids_map.into_iter() { - let mut grid_path: &String = &String::from(""); - - if original_paths.get(appid.as_str()).is_some() && original_paths.get(appid.as_str()).unwrap().get(grid_type.as_str()).is_some() { - grid_path = original_paths.get(appid.as_str()).unwrap().get(grid_type.as_str()).unwrap(); - } - - let grid_path_owned = grid_path.to_owned(); - let source_path_owned = source_path.to_owned(); - - if source_path_owned != grid_path_owned { - let target_path; - - if source_path != "REMOVE" { - let adjusted_path = adjust_path(app_handle, appid.as_str(), source_path_owned.as_str(), grid_type.as_str()).replace("\\", "/"); - if grid_type == "Icon" && !is_appid_shortcut(&appid, shortcut_icons) { - target_path = String::from(lib_cache_dir.join(adjusted_path).to_str().unwrap()).replace("\\", "/"); - } else { - target_path = String::from(grids_dir.join(adjusted_path).to_str().unwrap()).replace("\\", "/"); - } - } else { - target_path = String::from("REMOVE"); - } - - let mut changed_path = ChangedPath { - appId: appid.to_owned(), - gridType: grid_type.to_owned(), - oldPath: grid_path_owned.replace("\\", "/"), - targetPath: target_path.to_owned(), - sourcePath: source_path_owned.replace("\\", "/") - }; - - if changed_path.targetPath.ends_with(".webp") { - let target: String = changed_path.targetPath; - let mut jpg_target: String = target[..target.len() - 5].to_owned(); - jpg_target.push_str(".jpg"); - - changed_path.targetPath = String::from(jpg_target.to_owned()); - } - - res.push(changed_path); - } - } - } - - return res; -} - -/// Checks for shortcut grid changes. -fn check_for_shortcut_changes(shortcut_icons: &Map, original_shortcut_icons: &Map) -> bool { - for (shortcut_id, icon) in shortcut_icons.to_owned().into_iter() { - let icon: &str = icon.as_str().expect("Should have been able to convert icon to &str."); - let original_icon: &str = original_shortcut_icons.get(&shortcut_id).expect("Original hortcut should have had an icon.").as_str().expect("Should have been able to convert original icon to &str."); - - if icon != original_icon { - return true; - } - } - - return false; -} - -#[tauri::command] -/// Exports the users grids to a Grids zip file. -async fn export_grids_to_zip(app_handle: AppHandle, steam_path: String, steam_active_user_id: String, platform_id_map: Map, id_name_map: Map) -> bool { - let file_dialog = app_handle.dialog().file() - .set_title("Save Grids Zip") - .set_file_name("Steam_Grids_Export.zip") - .add_filter("zip", &["zip"]) - .set_directory(home_dir().expect("Should have been able to get home dir for zip.")); - - let file_path = file_dialog.blocking_save_file(); - - if file_path.is_some() { - let zip_path = file_path.unwrap(); - logger::log_to_core_file(app_handle.to_owned(), format!("Got save path: {}", zip_path.to_str().expect("Should have been able to convert path to string.")).as_str(), 0); - - let grids_dir_path = steam::get_grids_directory(app_handle.to_owned(), steam_path, steam_active_user_id); - let succeeded = zip_controller::generate_grids_zip(&app_handle, PathBuf::from(grids_dir_path), zip_path, &platform_id_map, &id_name_map); - - if succeeded { - logger::log_to_core_file(app_handle.to_owned(), "Successfully saved the user's grids.", 0); - return true; - } else { - logger::log_to_core_file(app_handle.to_owned(), "Failed to save the user's grids.", 0); - return false; - } - } else { - logger::log_to_core_file(app_handle.to_owned(), "No save location was chosen.", 0); - return false; - } -} - -#[tauri::command] -/// Sets the users grids from a Grids zip file. -async fn import_grids_from_zip(app_handle: AppHandle, steam_path: String, steam_active_user_id: String, name_id_map: Map) -> (bool, Map) { - let file_dialog = app_handle.dialog().file() - .set_title("Pick a Grids Zip") - .add_filter("zip", &["zip"]) - .set_directory(home_dir().expect("Should have been able to get home dir for zip.")); - - let file_path = file_dialog.blocking_save_file(); - - if file_path.is_some() { - let zip_path = file_path.unwrap(); - logger::log_to_core_file(app_handle.to_owned(), format!("Got file path: {}", zip_path.to_str().expect("Should have been able to convert path to string.")).as_str(), 0); - - let grids_dir_path = steam::get_grids_directory(app_handle.to_owned(), steam_path, steam_active_user_id); - let (success, icon_map) = zip_controller::set_grids_from_zip(&app_handle, PathBuf::from(grids_dir_path), zip_path, &name_id_map); - - if success { - logger::log_to_core_file(app_handle.to_owned(), "Successfully set the user's grids.", 0); - return (success, icon_map); - } else { - logger::log_to_core_file(app_handle.to_owned(), "Failed to set the user's grids.", 0); - return (success, icon_map); - } - } else { - logger::log_to_core_file(app_handle.to_owned(), "No zip file was selected by user.", 0); - return (false, Map::new()); - } -} - -#[tauri::command] -/// Reads the user's appinfo.vdf file. -async fn read_appinfo_vdf(app_handle: AppHandle, steam_path: String) -> String { - let appinfo_path: PathBuf = PathBuf::from(steam::get_appinfo_path(app_handle.to_owned(), steam_path)); - let appinfo_vdf: Map = open_appinfo_vdf(&appinfo_path); - return serde_json::to_string(&appinfo_vdf).expect("Should have been able to serialize AppInfo vdf to string."); -} - -#[tauri::command] -/// Reads the user's shortcuts.vdf file. -async fn read_shortcuts_vdf(app_handle: AppHandle, steam_path: String, steam_active_user_id: String) -> String { - let shortcuts_path = PathBuf::from(steam::get_shortcuts_path(app_handle.to_owned(), steam_path, steam_active_user_id)); - - if shortcuts_path.as_path().exists() { - logger::log_to_core_file(app_handle.to_owned(), "shortcuts.vdf exists, reading...", 0); - let shortcuts_array = open_shortcuts_vdf(&shortcuts_path); - return serde_json::to_string(&shortcuts_array).expect("Should have been able to serialize Shortcuts vdf to string."); - } else { - logger::log_to_core_file(app_handle.to_owned(), "shortcuts.vdf does not exist.", 0); - return "{}".to_owned(); - } -} - -#[tauri::command] -/// Reads the user's localconfig.vdf file. -async fn read_localconfig_vdf(app_handle: AppHandle, steam_path: String, steam_active_user_id: String) -> String { - let localconfig_path = PathBuf::from(steam::get_localconfig_path(app_handle.to_owned(), steam_path, steam_active_user_id)); - - if localconfig_path.as_path().exists() { - logger::log_to_core_file(app_handle.to_owned(), "localconfig.vdf exists, reading...", 0); - let localconfig_contents: String = fs::read_to_string(localconfig_path).expect("localconfig.vdf should have existed.").parse().expect("File should have been a text file."); - - let mut appids: Vec = Vec::new(); - - let mut is_reading_appids: bool = false; - - for line in localconfig_contents.split("\n") { - if line == "\t\t\t\t\"apps\"" { - is_reading_appids = true; - continue; - } - - if is_reading_appids { - if line.starts_with("\t\t\t\t\t\"") { - let length = line.chars().count(); - let appid_res = line.get(6..(length - 1)); - let appid = appid_res.expect("appid_res should have been ok"); - appids.push(appid.to_string()); - } - - if line == "\t\t\t\t}" { - break; - } - } - } - - return serde_json::to_string(&appids).expect("Should have been able to serialize localconfig vdf to string."); - } else { - logger::log_to_core_file(app_handle.to_owned(), "localconfig.vdf does not exist.", 0); - return "{}".to_owned(); - } -} - -#[tauri::command] -/// Applies the changes the user has made. -async fn save_changes(app_handle: AppHandle, steam_path: String, steam_active_user_id: String, current_art: String, original_art: String, shortcuts_str: String, shortcut_icons: Map, original_shortcut_icons: Map, changed_logo_positions: Map) -> String { - let current_art_dict: GridImageCache = serde_json::from_str(current_art.as_str()).unwrap(); - let original_art_dict: GridImageCache = serde_json::from_str(original_art.as_str()).unwrap(); - - logger::log_to_core_file(app_handle.to_owned(), "Converting current path entries to grid paths...", 0); - let paths_to_set: Vec = filter_paths(&app_handle, steam_path.to_owned(), steam_active_user_id.clone(), ¤t_art_dict, &original_art_dict, &shortcut_icons); - let paths_id_map: HashMap = paths_to_set.clone().iter().map(| entry | (format!("{}_{}", entry.appId.to_owned(), entry.gridType.to_owned()).to_string(), entry.to_owned())).collect(); - logger::log_to_core_file(app_handle.to_owned(), "Current path entries converted to grid paths.", 0); - - for changed_path in (&paths_to_set).into_iter() { - let source = changed_path.sourcePath.to_owned(); - let target = changed_path.targetPath.to_owned(); - - if target == String::from("REMOVE") { - if changed_path.oldPath.contains("grid") { - let remove_res = fs::remove_file(changed_path.oldPath.to_owned()); - if remove_res.is_err() { - let err = remove_res.err().unwrap(); - return format!("{{ \"error\": \"{}\"}}", err.to_string()); - } - logger::log_to_core_file(app_handle.to_owned(), format!("Removed grid {}.", changed_path.oldPath.to_owned()).as_str(), 0); - } - } else { - if changed_path.oldPath.contains("grid") { - let remove_res = fs::remove_file(changed_path.oldPath.to_owned()); - if remove_res.is_err() { - let err = remove_res.err().unwrap(); - return format!("{{ \"error\": \"{}\"}}", err.to_string()); - } - } - - fs::File::create(target.clone()).unwrap(); - - let copy_res = fs::copy(source.clone(), target.clone()); - - if copy_res.is_ok() { - logger::log_to_core_file(app_handle.to_owned(), format!("Copied {} to {}.", source, target).as_str(), 0); - } else { - logger::log_to_core_file(app_handle.to_owned(), format!("Failed to copy {} to {}.", source, target).as_str(), 2); - let err = copy_res.err().unwrap(); - return format!("{{ \"error\": \"{}\"}}", err.to_string()); - } - } - } - - let grids_directory: PathBuf = PathBuf::from(steam::get_grids_directory(app_handle.to_owned(), steam_path.to_owned(), steam_active_user_id.clone())); - for (appid, steam_logo_str_val) in changed_logo_positions.into_iter() { - let steam_logo_str: &str = steam_logo_str_val.as_str().expect("Should have been able to convert steamLogo pos into str."); - let logo_config_path: PathBuf = grids_directory.join(format!("{}.json", appid)); - - if steam_logo_str == "REMOVE" { - let remove_res = fs::remove_file(logo_config_path); - if remove_res.is_err() { - let err = remove_res.err().unwrap(); - return format!("{{ \"error\": \"{}\"}}", err.to_string()); - } - logger::log_to_core_file(app_handle.to_owned(), format!("Removed logo position config for {}.", appid).as_str(), 0); - } else { - let write_res = fs::write(&logo_config_path, steam_logo_str); - - if write_res.is_ok() { - logger::log_to_core_file(app_handle.to_owned(), format!("Wrote logo pos to config for {}.", appid).as_str(), 0); - } else { - logger::log_to_core_file(app_handle.to_owned(), format!("Failed to write logo pos to config for {}.", appid).as_str(), 2); - let err = write_res.err().unwrap(); - return format!("{{ \"error\": \"{}\"}}", err.to_string()); - } - } - } - - let should_change_shortcuts: bool = check_for_shortcut_changes(&shortcut_icons, &original_shortcut_icons); - - if should_change_shortcuts { - logger::log_to_core_file(app_handle.to_owned(), "Changes to shortcuts detected. Writing shortcuts.vdf...", 0); - let mut shortcuts_data: Value = serde_json::from_str(shortcuts_str.as_str()).expect("Should have been able to parse json string."); - - let shortcuts_obj_map: &mut Value = shortcuts_data.get_mut("shortcuts").expect("key: shortcuts should have existed."); - let shortcuts_map: &mut Map = shortcuts_obj_map.as_object_mut().expect("Should have been able to convert shortcuts to map"); - - for (_, shortcut) in shortcuts_map.into_iter() { - let shortcut_map: &mut Map = shortcut.as_object_mut().expect("should have been able to convert shortcut to map."); - let shortcut_appid_val: &Value = shortcut_map.get("appid").expect("shortcut should have had an appid"); - let shortcut_appid_num: i64 = shortcut_appid_val.as_i64().expect("should have been able to convert shortcut appid to str."); - let shortcut_appid: String = shortcut_appid_num.to_string(); - - let path_key: String = format!("{}_icon", shortcut_appid.to_owned()).to_string(); - - if paths_id_map.contains_key(&path_key) { - let changed_path: &ChangedPath = paths_id_map.get(&path_key).expect("entry should have existed."); - shortcut_map.insert(String::from("icon"), Value::String(changed_path.targetPath.to_owned())); - } - } - - let mut modified_shortcuts_data: Map = Map::new(); - modified_shortcuts_data.insert(String::from("shortcuts"), shortcuts_obj_map.to_owned()); - shortcuts_data = Value::Object(modified_shortcuts_data); - - let shortcuts_vdf_path: PathBuf = PathBuf::from(steam::get_shortcuts_path(app_handle.to_owned(), steam_path.to_owned(), steam_active_user_id)); - write_shortcuts_vdf(&shortcuts_vdf_path, shortcuts_data); - logger::log_to_core_file(app_handle.to_owned(), "Changes to shortcuts saved.", 0); - } else { - logger::log_to_core_file(app_handle.to_owned(), "No changes to shortcuts detected. Skipping...", 0); - } - - let changed_res = serde_json::to_string::>(paths_to_set.as_ref()); - - if changed_res.is_ok() { - return changed_res.unwrap(); - } else { - let err = changed_res.err().unwrap(); - logger::log_to_core_file(app_handle, format!("{}", err.to_string()).as_str(), 2); - return String::from("[]"); - } -} - -#[tauri::command] -/// Writes the user's shortcuts.vdf file. -async fn write_shortcuts(app_handle: AppHandle, steam_path: String, steam_active_user_id: String, shortcuts_str: String) -> bool { - logger::log_to_core_file(app_handle.to_owned(), "Writing shortcuts.vdf...", 0); - let shortcuts_vdf_path: PathBuf = PathBuf::from(steam::get_shortcuts_path(app_handle.to_owned(), steam_path, steam_active_user_id)); - let shortcuts_data: Value = serde_json::from_str(shortcuts_str.as_str()).expect("Should have been able to parse json string."); - - let success: bool = write_shortcuts_vdf(&shortcuts_vdf_path, shortcuts_data); - - if success { - logger::log_to_core_file(app_handle.to_owned(), "Changes to shortcuts saved.", 0); - return true; - } else { - logger::log_to_core_file(app_handle.to_owned(), "Changes to shortcuts failed.", 0); - return false; - } -} - #[tauri::command] /// Downloads a file from a url. async fn download_grid(app_handle: AppHandle, grid_url: String, dest_path: String, timeout: u64) -> String { @@ -446,88 +61,6 @@ async fn download_grid(app_handle: AppHandle, grid_url: String, dest_path: Strin } } -#[tauri::command] -/// Downloads a file from a url. -async fn clean_grids(app_handle: AppHandle, steam_path: String, steam_active_user_id: String, preset: String, all_appids: String, selected_game_ids: String) -> String { - logger::log_to_core_file(app_handle.to_owned(), format!("Starting {} grid cleaning.", preset).as_str(), 0); - - let appids_arr: Vec = serde_json::from_str(all_appids.as_str()).expect("Should have been able to deserialize appids array."); - - let grids_dir_path: String = steam::get_grids_directory(app_handle.to_owned(), steam_path, steam_active_user_id); - let grids_dir_contents = fs::read_dir(grids_dir_path).unwrap(); - - let mut found_apps: HashMap = HashMap::new(); - let mut conflicts: Vec = Vec::new(); - - - if preset == String::from("clean") { - for dir_entry in grids_dir_contents { - let entry = dir_entry.expect("Should have been able to get directory entry."); - - if entry.file_type().unwrap().is_file() { - let full_file_path: PathBuf = entry.path(); - let full_file_path_str: &str = full_file_path.to_str().unwrap(); - let filename = entry.file_name(); - let filename_str: &str = filename.to_str().unwrap(); - - let (id, grid_type) = zip_controller::get_id_from_grid_name(filename_str); - let id_type_str: String = format!("{}_{}", id, grid_type); - - if appids_arr.contains(&id) { - if found_apps.contains_key(&id_type_str) { - // ? There's a conflict - let (other_filename, other_full_path) = found_apps.get(&id_type_str).expect("Map should have contained the id_type_str."); - - conflicts.push(CleanConflicts { fileAPath: other_full_path.to_owned(), fileAName: other_filename.to_owned(), fileBPath: String::from(full_file_path_str), fileBName: String::from(filename_str), appid: id.clone(), gridType: grid_type.clone() }); - - logger::log_to_core_file(app_handle.to_owned(), format!("Detected conflict between {} and {}.", filename_str, other_filename).as_str(), 0); - } else { - found_apps.insert(id_type_str, (String::from(filename_str), String::from(full_file_path_str))); - } - } else { - let remove_res = fs::remove_file(full_file_path); - if remove_res.is_err() { - let err = remove_res.err().unwrap(); - return format!("{{ \"error\": \"{}\"}}", err.to_string()); - } - - logger::log_to_core_file(app_handle.to_owned(), format!("Deleted {}.", filename_str).as_str(), 0); - } - } - } - } else { - let game_ids_arr: Vec = serde_json::from_str(selected_game_ids.as_str()).expect("Should have been able to deserialize selected appids array."); - - for dir_entry in grids_dir_contents { - let entry = dir_entry.expect("Should have been able to get directory entry."); - - if entry.file_type().unwrap().is_file() { - let full_file_path: PathBuf = entry.path(); - let filename = entry.file_name(); - let filename_str: &str = filename.to_str().unwrap(); - - let (id, _) = zip_controller::get_id_from_grid_name(filename_str); - - if game_ids_arr.contains(&id) { - let remove_res = fs::remove_file(full_file_path); - if remove_res.is_err() { - let err = remove_res.err().unwrap(); - return format!("{{ \"error\": \"{}\"}}", err.to_string()); - } - - logger::log_to_core_file(app_handle.to_owned(), format!("Deleted {}.", filename_str).as_str(), 0); - } - } - } - } - - - logger::log_to_core_file(app_handle.to_owned(), format!("{} grid cleaning complete.", preset).as_str(), 0); - - return serde_json::to_string(&conflicts).expect("Should have been able to serialize conflict array."); -} - - #[tauri::command] // Validates the steam install path async fn validate_steam_path(app_handle: AppHandle, target_path: String) -> bool { @@ -641,15 +174,15 @@ fn main() { add_path_to_scope, toggle_dev_tools, add_steam_to_scope, - export_grids_to_zip, - import_grids_from_zip, - read_appinfo_vdf, - read_shortcuts_vdf, - read_localconfig_vdf, - save_changes, - write_shortcuts, + zip_controller::export_grids_to_zip, + zip_controller::import_grids_from_zip, + steam::read_appinfo_vdf, + steam::read_shortcuts_vdf, + steam::read_localconfig_vdf, + handle_changes::save_changes, + handle_changes::write_shortcuts, download_grid, - clean_grids, + clean_grids::clean_grids, validate_steam_path ]) .plugin(tauri_plugin_fs::init()) diff --git a/src-tauri/src/appinfo_vdf_parser.rs b/src-tauri/src/parsers/appinfo_vdf_parser.rs similarity index 99% rename from src-tauri/src/appinfo_vdf_parser.rs rename to src-tauri/src/parsers/appinfo_vdf_parser.rs index 2c666c88..ff40c1a5 100644 --- a/src-tauri/src/appinfo_vdf_parser.rs +++ b/src-tauri/src/parsers/appinfo_vdf_parser.rs @@ -6,7 +6,7 @@ use serde_json::{Value, Map}; use rayon::iter::{IntoParallelRefIterator, ParallelIterator}; use crate::reader::Reader; -use crate::vdf_reader::read_entry_map; +use super::vdf_reader::read_entry_map; /// Opens the appinfo.vdf file and returns the values as JSON. pub fn open_appinfo_vdf(path: &PathBuf) -> Map { diff --git a/src-tauri/src/parsers/mod.rs b/src-tauri/src/parsers/mod.rs new file mode 100644 index 00000000..4dddbb5c --- /dev/null +++ b/src-tauri/src/parsers/mod.rs @@ -0,0 +1,4 @@ +mod vdf_structs; +mod vdf_reader; +pub mod appinfo_vdf_parser; +pub mod shortcuts_vdf_parser; \ No newline at end of file diff --git a/src-tauri/src/shortcuts_vdf_parser.rs b/src-tauri/src/parsers/shortcuts_vdf_parser.rs similarity index 98% rename from src-tauri/src/shortcuts_vdf_parser.rs rename to src-tauri/src/parsers/shortcuts_vdf_parser.rs index c0a60f34..bf2e5a31 100644 --- a/src-tauri/src/shortcuts_vdf_parser.rs +++ b/src-tauri/src/parsers/shortcuts_vdf_parser.rs @@ -4,8 +4,8 @@ use std::io::{Read, Write}; use serde_json::{ Value, Map }; use crate::reader::Reader; -use crate::vdf_reader::read_entry_map; use crate::writer::Writer; +use super::vdf_reader::read_entry_map; /// Opens the shortcuts.vdf file and returns the values as JSON. pub fn open_shortcuts_vdf(path: &PathBuf) -> Value { diff --git a/src-tauri/src/vdf_reader.rs b/src-tauri/src/parsers/vdf_reader.rs similarity index 100% rename from src-tauri/src/vdf_reader.rs rename to src-tauri/src/parsers/vdf_reader.rs diff --git a/src-tauri/src/vdf_structs.rs b/src-tauri/src/parsers/vdf_structs.rs similarity index 100% rename from src-tauri/src/vdf_structs.rs rename to src-tauri/src/parsers/vdf_structs.rs diff --git a/src-tauri/src/steam.rs b/src-tauri/src/steam.rs index 1f586845..a71c43ef 100644 --- a/src-tauri/src/steam.rs +++ b/src-tauri/src/steam.rs @@ -1,5 +1,7 @@ use crate::logger; +use crate::parsers::appinfo_vdf_parser::open_appinfo_vdf; +use crate::parsers::shortcuts_vdf_parser::open_shortcuts_vdf; use std::fs::{self, create_dir_all}; use std::path::{ PathBuf, Path }; @@ -241,4 +243,67 @@ pub fn get_steam_users(app_handle: AppHandle, steam_path: String) -> String { logger::log_to_core_file(app_handle.to_owned(), format!("Loaded {} steam users.", steam_users.len()).as_str(), 0); return serde_json::to_string(&steam_users).unwrap(); -} \ No newline at end of file +} + +#[tauri::command] +/// Reads the user's appinfo.vdf file. +pub async fn read_appinfo_vdf(app_handle: AppHandle, steam_path: String) -> String { + let appinfo_path: PathBuf = PathBuf::from(get_appinfo_path(app_handle.to_owned(), steam_path)); + let appinfo_vdf: Map = open_appinfo_vdf(&appinfo_path); + return serde_json::to_string(&appinfo_vdf).expect("Should have been able to serialize AppInfo vdf to string."); +} + +#[tauri::command] +/// Reads the user's shortcuts.vdf file. +pub async fn read_shortcuts_vdf(app_handle: AppHandle, steam_path: String, steam_active_user_id: String) -> String { + let shortcuts_path = PathBuf::from(get_shortcuts_path(app_handle.to_owned(), steam_path, steam_active_user_id)); + + if shortcuts_path.as_path().exists() { + logger::log_to_core_file(app_handle.to_owned(), "shortcuts.vdf exists, reading...", 0); + let shortcuts_array = open_shortcuts_vdf(&shortcuts_path); + return serde_json::to_string(&shortcuts_array).expect("Should have been able to serialize Shortcuts vdf to string."); + } else { + logger::log_to_core_file(app_handle.to_owned(), "shortcuts.vdf does not exist.", 0); + return "{}".to_owned(); + } +} + +#[tauri::command] +/// Reads the user's localconfig.vdf file. +pub async fn read_localconfig_vdf(app_handle: AppHandle, steam_path: String, steam_active_user_id: String) -> String { + let localconfig_path = PathBuf::from(get_localconfig_path(app_handle.to_owned(), steam_path, steam_active_user_id)); + + if localconfig_path.as_path().exists() { + logger::log_to_core_file(app_handle.to_owned(), "localconfig.vdf exists, reading...", 0); + let localconfig_contents: String = fs::read_to_string(localconfig_path).expect("localconfig.vdf should have existed.").parse().expect("File should have been a text file."); + + let mut appids: Vec = Vec::new(); + + let mut is_reading_appids: bool = false; + + for line in localconfig_contents.split("\n") { + if line == "\t\t\t\t\"apps\"" { + is_reading_appids = true; + continue; + } + + if is_reading_appids { + if line.starts_with("\t\t\t\t\t\"") { + let length = line.chars().count(); + let appid_res = line.get(6..(length - 1)); + let appid = appid_res.expect("appid_res should have been ok"); + appids.push(appid.to_string()); + } + + if line == "\t\t\t\t}" { + break; + } + } + } + + return serde_json::to_string(&appids).expect("Should have been able to serialize localconfig vdf to string."); + } else { + logger::log_to_core_file(app_handle.to_owned(), "localconfig.vdf does not exist.", 0); + return "{}".to_owned(); + } +} diff --git a/src-tauri/src/logger.rs b/src-tauri/src/utils/logger.rs similarity index 100% rename from src-tauri/src/logger.rs rename to src-tauri/src/utils/logger.rs diff --git a/src-tauri/src/utils/mod.rs b/src-tauri/src/utils/mod.rs new file mode 100644 index 00000000..76c05f42 --- /dev/null +++ b/src-tauri/src/utils/mod.rs @@ -0,0 +1,3 @@ +pub mod logger; +pub mod reader; +pub mod writer; \ No newline at end of file diff --git a/src-tauri/src/reader.rs b/src-tauri/src/utils/reader.rs similarity index 100% rename from src-tauri/src/reader.rs rename to src-tauri/src/utils/reader.rs diff --git a/src-tauri/src/writer.rs b/src-tauri/src/utils/writer.rs similarity index 100% rename from src-tauri/src/writer.rs rename to src-tauri/src/utils/writer.rs diff --git a/src-tauri/src/zip_controller.rs b/src-tauri/src/zip_controller.rs index 5267c9cf..8fec5161 100644 --- a/src-tauri/src/zip_controller.rs +++ b/src-tauri/src/zip_controller.rs @@ -1,11 +1,14 @@ -use crate::logger; +use crate::{logger, steam}; use std::{path::PathBuf, io::{BufReader, self, Write}, fs::{File, read_dir, read}}; use serde_json::{Map, Value}; use tauri::AppHandle; +use tauri_plugin_dialog::DialogExt; use zip; +use home::home_dir; + /// Gets the id for a grid from its name. pub fn get_id_from_grid_name(grid_name: &str) -> (String, String) { let dot_index: usize = grid_name.find(".").expect("File should have had a file extension"); @@ -115,9 +118,10 @@ fn get_import_grid_name(app_handle: &AppHandle, filename: &str, name_id_map: &Ma } } + #[allow(unused)] /// Generates a Grids zip file export. -pub fn generate_grids_zip(app_handle: &AppHandle, grids_dir_path: PathBuf, zip_file_path: PathBuf, platform_id_map: &Map, id_name_map: &Map) -> bool { +fn generate_grids_zip(app_handle: &AppHandle, grids_dir_path: PathBuf, zip_file_path: PathBuf, platform_id_map: &Map, id_name_map: &Map) -> bool { let grids_dir_contents = read_dir(grids_dir_path).unwrap(); let zip_file: File = File::create(zip_file_path).expect("File's directory should have existed since user picked it."); let mut zip_writer: zip::ZipWriter = zip::ZipWriter::new(zip_file); @@ -127,27 +131,31 @@ pub fn generate_grids_zip(app_handle: &AppHandle, grids_dir_path: PathBuf, zip_f for dir_entry in grids_dir_contents { let entry = dir_entry.expect("Should have been able to get directory entry."); - if entry.file_type().unwrap().is_file() { - let contents: Vec = read(entry.path()).expect("Should have been able to read file, but couldn't."); - let filename = entry.file_name(); - let filename_str: &str = filename.to_str().unwrap(); - let mut in_zip_filename: String = String::from(filename_str); - let (id, grid_type) = get_id_from_grid_name(filename_str); - - if platform_id_map.contains_key(&id) { - let platform_value: &Value = platform_id_map.get(&id).expect("Platform map should have contained game/shortcut id."); - let platform: &str = platform_value.as_str().expect("Should have been able to convert platform to string."); - - let modified_filename = construct_grid_export_name(filename_str, &id, &grid_type, platform, id_name_map); - in_zip_filename = modified_filename; - } + if !entry.file_type().unwrap().is_file() { + logger::log_to_core_file(app_handle.to_owned(), format!("Grid entry {} is a directory, skipping...", entry.file_name().to_str().unwrap()).as_str(), 1); + continue; + } - zip_writer.start_file(in_zip_filename, entry_options); - zip_writer.write(&contents); - logger::log_to_core_file(app_handle.to_owned(), format!("Wrote entry {} to zip.", entry.file_name().to_str().unwrap()).as_str(), 0); - } else { - logger::log_to_core_file(app_handle.to_owned(), format!("Zip entry {} is a directory, skipping...", entry.file_name().to_str().unwrap()).as_str(), 1); + let contents: Vec = read(entry.path()).expect("Should have been able to read file, but couldn't."); + let filename = entry.file_name(); + let filename_str: &str = filename.to_str().unwrap(); + let mut in_zip_filename: String = String::from(filename_str); + let (id, grid_type) = get_id_from_grid_name(filename_str); + + if !platform_id_map.contains_key(&id) { + logger::log_to_core_file(app_handle.to_owned(), format!("Grid entry {} is not in appids list, skipping...", entry.file_name().to_str().unwrap()).as_str(), 1); + continue; } + + let platform_value: &Value = platform_id_map.get(&id).expect("Platform map should have contained game/shortcut id."); + let platform: &str = platform_value.as_str().expect("Should have been able to convert platform to string."); + + let modified_filename = construct_grid_export_name(filename_str, &id, &grid_type, platform, id_name_map); + in_zip_filename = modified_filename; + + zip_writer.start_file(in_zip_filename, entry_options); + zip_writer.write(&contents); + logger::log_to_core_file(app_handle.to_owned(), format!("Wrote entry {} to zip.", entry.file_name().to_str().unwrap()).as_str(), 0); } zip_writer.finish(); @@ -156,7 +164,7 @@ pub fn generate_grids_zip(app_handle: &AppHandle, grids_dir_path: PathBuf, zip_f } /// Sets the users grids from a Grids zip file. -pub fn set_grids_from_zip(app_handle: &AppHandle, grids_dir_path: PathBuf, zip_file_path: PathBuf, name_id_map: &Map) -> (bool, Map) { +fn set_grids_from_zip(app_handle: &AppHandle, grids_dir_path: PathBuf, zip_file_path: PathBuf, name_id_map: &Map) -> (bool, Map) { let mut icon_map: Map = Map::new(); let zip_file = File::open(zip_file_path).expect("File should have existed since user picked it."); @@ -191,4 +199,66 @@ pub fn set_grids_from_zip(app_handle: &AppHandle, grids_dir_path: PathBuf, zip_f } return (true, icon_map); -} \ No newline at end of file +} + + +#[tauri::command] +/// Exports the users grids to a Grids zip file. +pub async fn export_grids_to_zip(app_handle: AppHandle, steam_path: String, steam_active_user_id: String, platform_id_map: Map, id_name_map: Map) -> bool { + let file_dialog = app_handle.dialog().file() + .set_title("Save Grids Zip") + .set_file_name("Steam_Grids_Export.zip") + .add_filter("zip", &["zip"]) + .set_directory(home_dir().expect("Should have been able to get home dir for zip.")); + + let file_path = file_dialog.blocking_save_file(); + + if file_path.is_some() { + let zip_path = file_path.unwrap(); + logger::log_to_core_file(app_handle.to_owned(), format!("Got save path: {}", zip_path.to_str().expect("Should have been able to convert path to string.")).as_str(), 0); + + let grids_dir_path = steam::get_grids_directory(app_handle.to_owned(), steam_path, steam_active_user_id); + let succeeded = generate_grids_zip(&app_handle, PathBuf::from(grids_dir_path), zip_path, &platform_id_map, &id_name_map); + + if succeeded { + logger::log_to_core_file(app_handle.to_owned(), "Successfully saved the user's grids.", 0); + return true; + } + + logger::log_to_core_file(app_handle.to_owned(), "Failed to save the user's grids.", 0); + return false; + } + + logger::log_to_core_file(app_handle.to_owned(), "No save location was chosen.", 0); + return false; +} + +#[tauri::command] +/// Sets the users grids from a Grids zip file. +pub async fn import_grids_from_zip(app_handle: AppHandle, steam_path: String, steam_active_user_id: String, name_id_map: Map) -> (bool, Map) { + let file_dialog = app_handle.dialog().file() + .set_title("Pick a Grids Zip") + .add_filter("zip", &["zip"]) + .set_directory(home_dir().expect("Should have been able to get home dir for zip.")); + + let file_path = file_dialog.blocking_save_file(); + + if file_path.is_some() { + let zip_path = file_path.unwrap(); + logger::log_to_core_file(app_handle.to_owned(), format!("Got file path: {}", zip_path.to_str().expect("Should have been able to convert path to string.")).as_str(), 0); + + let grids_dir_path = steam::get_grids_directory(app_handle.to_owned(), steam_path, steam_active_user_id); + let (success, icon_map) = set_grids_from_zip(&app_handle, PathBuf::from(grids_dir_path), zip_path, &name_id_map); + + if success { + logger::log_to_core_file(app_handle.to_owned(), "Successfully set the user's grids.", 0); + return (success, icon_map); + } + + logger::log_to_core_file(app_handle.to_owned(), "Failed to set the user's grids.", 0); + return (success, icon_map); + } + + logger::log_to_core_file(app_handle.to_owned(), "No zip file was selected by user.", 0); + return (false, Map::new()); +} From c4313fa662bda3902ac61e953afe68ff2c5d1150 Mon Sep 17 00:00:00 2001 From: Travis Lane <63308171+Tormak9970@users.noreply.github.com> Date: Fri, 15 Nov 2024 11:59:35 -0500 Subject: [PATCH 2/2] fix: grids import now works properly --- src-tauri/src/zip_controller.rs | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/src-tauri/src/zip_controller.rs b/src-tauri/src/zip_controller.rs index 8fec5161..79d0a8c6 100644 --- a/src-tauri/src/zip_controller.rs +++ b/src-tauri/src/zip_controller.rs @@ -119,7 +119,6 @@ fn get_import_grid_name(app_handle: &AppHandle, filename: &str, name_id_map: &Ma } -#[allow(unused)] /// Generates a Grids zip file export. fn generate_grids_zip(app_handle: &AppHandle, grids_dir_path: PathBuf, zip_file_path: PathBuf, platform_id_map: &Map, id_name_map: &Map) -> bool { let grids_dir_contents = read_dir(grids_dir_path).unwrap(); @@ -139,7 +138,6 @@ fn generate_grids_zip(app_handle: &AppHandle, grids_dir_path: PathBuf, zip_file_ let contents: Vec = read(entry.path()).expect("Should have been able to read file, but couldn't."); let filename = entry.file_name(); let filename_str: &str = filename.to_str().unwrap(); - let mut in_zip_filename: String = String::from(filename_str); let (id, grid_type) = get_id_from_grid_name(filename_str); if !platform_id_map.contains_key(&id) { @@ -151,14 +149,14 @@ fn generate_grids_zip(app_handle: &AppHandle, grids_dir_path: PathBuf, zip_file_ let platform: &str = platform_value.as_str().expect("Should have been able to convert platform to string."); let modified_filename = construct_grid_export_name(filename_str, &id, &grid_type, platform, id_name_map); - in_zip_filename = modified_filename; + let in_zip_filename = modified_filename; - zip_writer.start_file(in_zip_filename, entry_options); - zip_writer.write(&contents); + let _ = zip_writer.start_file(in_zip_filename, entry_options); + let _ = zip_writer.write(&contents); logger::log_to_core_file(app_handle.to_owned(), format!("Wrote entry {} to zip.", entry.file_name().to_str().unwrap()).as_str(), 0); } - zip_writer.finish(); + let _ = zip_writer.finish(); logger::log_to_core_file(app_handle.to_owned(), "Successfully wrote export zip.", 0); return true; } @@ -241,10 +239,10 @@ pub async fn import_grids_from_zip(app_handle: AppHandle, steam_path: String, st .add_filter("zip", &["zip"]) .set_directory(home_dir().expect("Should have been able to get home dir for zip.")); - let file_path = file_dialog.blocking_save_file(); + let file_path = file_dialog.blocking_pick_file(); if file_path.is_some() { - let zip_path = file_path.unwrap(); + let zip_path = file_path.unwrap().path; logger::log_to_core_file(app_handle.to_owned(), format!("Got file path: {}", zip_path.to_str().expect("Should have been able to convert path to string.")).as_str(), 0); let grids_dir_path = steam::get_grids_directory(app_handle.to_owned(), steam_path, steam_active_user_id);