diff --git a/src-tauri/src/filesystem/explorer.rs b/src-tauri/src/filesystem/explorer.rs index abafd7e..7fb0410 100644 --- a/src-tauri/src/filesystem/explorer.rs +++ b/src-tauri/src/filesystem/explorer.rs @@ -1,8 +1,15 @@ use std::fs; use std::fs::read_dir; +use std::ops::Deref; +use std::path::{Path, PathBuf}; +use notify::event::CreateKind; +use tauri::State; use crate::errors::Error; +use crate::filesystem::cache::FsEventHandler; +use crate::filesystem::fs_utils; +use crate::filesystem::fs_utils::get_mount_point; use crate::filesystem::volume::DirectoryChild; -use crate::filesystem::volume::DirectoryChild::File; +use crate::StateSafe; /// Opens a file at the given path. Returns a string if there was an error. // NOTE(conaticus): I tried handling the errors nicely here but Tauri was mega cringe and wouldn't let me nest results in async functions, so used string error messages instead. @@ -49,11 +56,68 @@ pub async fn open_directory(path: String) -> Result, ()> { .collect()) } + #[tauri::command] -pub async fn create_file(path: String) -> Result<(), Error> { +pub async fn create_file(state_mux: State<'_, StateSafe>, path: String) -> Result<(), Error> { + let mount_point_str = get_mount_point(path.clone()).unwrap_or_default(); + + let fs_event_manager = FsEventHandler::new(state_mux.deref().clone(), mount_point_str.into()); + fs_event_manager.handle_create(CreateKind::File, Path::new(&path)); + let res = fs::File::create(path); match res { - Ok(_) => Ok(()), + Ok(_) => { + Ok(()) + }, + Err(err) => Err(Error::Custom(err.to_string())), + } +} + +#[tauri::command] +pub async fn create_directory(state_mux: State<'_, StateSafe>, path: String) -> Result<(), Error> { + let mount_point_str = get_mount_point(path.clone()).unwrap_or_default(); + + let fs_event_manager = FsEventHandler::new(state_mux.deref().clone(), mount_point_str.into()); + fs_event_manager.handle_create(CreateKind::Folder, Path::new(&path)); + + let res = fs::create_dir(path); + match res { + Ok(_) => { + Ok(()) + }, + Err(err) => Err(Error::Custom(err.to_string())), + } +} + +#[tauri::command] +pub async fn rename_file(state_mux: State<'_, StateSafe>, old_path: String, new_path: String) -> Result<(), Error> { + let mount_point_str = get_mount_point(old_path.clone()).unwrap_or_default(); + + let mut fs_event_manager = FsEventHandler::new(state_mux.deref().clone(), mount_point_str.into()); + fs_event_manager.handle_rename_from(Path::new(&old_path)); + fs_event_manager.handle_rename_to(Path::new(&new_path)); + + let res = fs::rename(old_path, new_path); + match res { + Ok(_) => { + Ok(()) + }, + Err(err) => Err(Error::Custom(err.to_string())), + } +} + +#[tauri::command] +pub async fn delete_file(state_mux: State<'_, StateSafe>, path: String) -> Result<(), Error> { + let mount_point_str = get_mount_point(path.clone()).unwrap_or_default(); + + let fs_event_manager = FsEventHandler::new(state_mux.deref().clone(), mount_point_str.into()); + fs_event_manager.handle_delete(Path::new(&path)); + + let res = fs::remove_file(path); + match res { + Ok(_) => { + Ok(()) + }, Err(err) => Err(Error::Custom(err.to_string())), } } \ No newline at end of file diff --git a/src-tauri/src/filesystem/fs_utils.rs b/src-tauri/src/filesystem/fs_utils.rs new file mode 100644 index 0000000..440ff30 --- /dev/null +++ b/src-tauri/src/filesystem/fs_utils.rs @@ -0,0 +1,12 @@ +use std::path::{Path, PathBuf}; + +pub fn get_mount_point(path: String) -> Option { + let path = Path::new(&path); + let root = path.components().next()?; + let mount_point = root.as_os_str().to_string_lossy().into_owned(); + + let mut mount_point_path = PathBuf::new(); + mount_point_path.push(&mount_point); + mount_point_path.push("\\"); + Some(mount_point_path.to_string_lossy().into_owned()) +} \ No newline at end of file diff --git a/src-tauri/src/filesystem/mod.rs b/src-tauri/src/filesystem/mod.rs index 17f61d6..3a3beea 100644 --- a/src-tauri/src/filesystem/mod.rs +++ b/src-tauri/src/filesystem/mod.rs @@ -1,6 +1,7 @@ pub mod explorer; pub mod cache; pub mod volume; +mod fs_utils; pub const DIRECTORY: &str = "directory"; pub const FILE: &str = "file"; diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs index 8d736f7..24bdff7 100644 --- a/src-tauri/src/main.rs +++ b/src-tauri/src/main.rs @@ -5,7 +5,7 @@ mod filesystem; mod search; mod errors; -use filesystem::explorer::{open_file, open_directory, create_file}; +use filesystem::explorer::{open_file, open_directory, create_file, create_directory, rename_file, delete_file}; use filesystem::volume::get_volumes; use search::search_directory; use serde::{Deserialize, Serialize}; @@ -37,7 +37,10 @@ async fn main() { open_directory, search_directory, open_file, - create_file + create_file, + create_directory, + rename_file, + delete_file ]) .manage(Arc::new(Mutex::new(AppState::default()))) .run(tauri::generate_context!()) diff --git a/src/App.tsx b/src/App.tsx index 76b111f..610f2f3 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -15,6 +15,7 @@ import { unselectDirectoryContents, updateDirectoryContents } from "./state/slices/currentDirectorySlice"; +import {DIRECTORY_ENTITY_ID} from "./components/MainBody/DirectoryEntity"; function App() { const [volumes, setVolumes] = useState([]); @@ -93,8 +94,13 @@ function App() { return (
{ - dispatch(unselectDirectoryContents()); handleCloseContextMenu(e); + + if (e.target instanceof HTMLElement) { + if (e.target.id === DIRECTORY_ENTITY_ID) return; + } + + dispatch(unselectDirectoryContents()); }} onContextMenu={handleMainContextMenu}> diff --git a/src/components/ContextMenus/ContextMenus.tsx b/src/components/ContextMenus/ContextMenus.tsx index b2090e0..0eb7d1e 100644 --- a/src/components/ContextMenus/ContextMenus.tsx +++ b/src/components/ContextMenus/ContextMenus.tsx @@ -26,7 +26,7 @@ export default function ContextMenus() { async function onNewFile(name: string) { try { - const path = generalPayload.currentPath + name; + const path = generalPayload.currentPath + "\\" + name; await createFile(path); const newDirectoryContent = {"File": [name, path]} as DirectoryContent;