From b94c06fce28ca795e6f515b8a6b81a8b08c41160 Mon Sep 17 00:00:00 2001 From: Adeoye Adefemi Date: Mon, 20 May 2024 00:28:45 +0100 Subject: [PATCH] app v-0.7.6: remove dead and depreciated codes --- desktop/core/Cargo.toml | 2 +- desktop/core/src/file_manager/file.rs | 40 +++- desktop/core/src/file_manager/mod.rs | 234 ++++++++++++++++++- desktop/core/src/file_manager/search.rs | 157 ------------- desktop/core/src/ipc_manager/fs.rs | 232 ------------------ desktop/core/src/ipc_manager/mod.rs | 3 +- desktop/core/src/main.rs | 6 +- desktop/core/src/network_manager/mod.rs | 5 + desktop/core/src/server/routes.rs | 1 + desktop/core/src/utils/fs.rs | 96 -------- desktop/core/src/utils/mod.rs | 37 +-- desktop/core/src/utils/shell.rs | 1 + desktop/core/src/utils/system_info.rs | 4 +- desktop/core/tauri.conf.json | 6 +- desktop/package.json | 3 + desktop/src/components/MediaViewer/index.tsx | 7 + desktop/src/components/nav/index.tsx | 15 +- desktop/yarn.lock | 21 ++ 18 files changed, 337 insertions(+), 533 deletions(-) delete mode 100644 desktop/core/src/file_manager/search.rs delete mode 100644 desktop/core/src/ipc_manager/fs.rs delete mode 100644 desktop/core/src/utils/fs.rs create mode 100644 desktop/src/components/MediaViewer/index.tsx diff --git a/desktop/core/Cargo.toml b/desktop/core/Cargo.toml index 861c18e8..2e16984a 100644 --- a/desktop/core/Cargo.toml +++ b/desktop/core/Cargo.toml @@ -37,7 +37,7 @@ serde_json = "1.0" sqlx = {version = "0.6.2", features = ["sqlite", "runtime-tokio-native-tls"] } sys-info = "0.9.1" sysinfo = "0.29.2" -tauri = {version = "1.2", features = [ "window-all", "app-all", "dialog-all", "fs-all", "path-all", "shell-open"] } +tauri = {version = "1.2", features = [ "clipboard-write-text", "window-all", "app-all", "dialog-all", "fs-all", "path-all", "shell-open"] } tokio = {version = "1.26.0", features = ["full"] } tokio-util = {version = "0.7", features = ["io"] } tower = {version = "0.4", features = ["util"] } diff --git a/desktop/core/src/file_manager/file.rs b/desktop/core/src/file_manager/file.rs index 59b7f1db..e0856571 100644 --- a/desktop/core/src/file_manager/file.rs +++ b/desktop/core/src/file_manager/file.rs @@ -1,4 +1,3 @@ -use crate::utils::fs::compute_file_size; use filesize::PathExt; use serde::{Deserialize, Serialize}; use std::path::PathBuf; @@ -8,6 +7,44 @@ use walkdir::DirEntry; extern crate dirs; use path_absolutize::*; + + + +/// a function to compute file size +/// accept files size in byte and parse it to human readable KB, MB, TB, GB e.t. +pub fn compute_file_size(size: u128) -> String { + if size > (1024 * 1024 * 1024 * 1024) { + format!("{:.2} TB", size / (1024 * 1024 * 1024 * 1024)) + } else if size > (1024 * 1024 * 1024) { + format!("{:.2} GB", size / (1024 * 1024 * 1024)) + } else if size > (1024 * 1024) { + format!("{:.2} MB", size / (1024 * 1024)) + } else if size > 1024 { + format!("{:.2} KB", size / (1024)) + } else { + format!("{:.2} B", size) + } +} + + + +#[derive(serde::Serialize, Debug)] +pub struct DriveInformation { + name: String, + mount_point: String, + total_space: u64, + available_space: u64, + is_removable: bool, + disk_type: String, + file_system: String, +} + +#[derive(serde::Serialize)] +pub struct Drives { + array_of_drives: Vec, +} + + // the file structure #[derive(Debug, Default, Serialize, Deserialize, TS)] #[serde(rename_all = "camelCase")] @@ -21,6 +58,7 @@ pub struct File { pub is_folder: bool, } +#[allow(unused)] impl File { // convert a DirEntry to a File pub fn from(entry: DirEntry) -> Self { diff --git a/desktop/core/src/file_manager/mod.rs b/desktop/core/src/file_manager/mod.rs index 8c24fd8f..3fb6163c 100644 --- a/desktop/core/src/file_manager/mod.rs +++ b/desktop/core/src/file_manager/mod.rs @@ -1,2 +1,234 @@ pub mod file; -pub mod search; + +use std::net::Ipv4Addr; +use std::path::PathBuf; +use crate::UPLOAD_PATH; +use crate::{ + file_manager::file::{get_files_in_directory, File}, + utils::{ApiResponse, CommandData}, +}; +use dirs; +use serde::{Deserialize, Serialize}; +use serde_json::{json, Value}; +use ts_rs::TS; + +use crate::database::{self, TransferHistory, TransferHistoryBuilder}; +use crate::network_manager::ip_manager; +use tokio::io::AsyncReadExt; + +/// the dir enum, reads, $HOME, $PICTURES, $VIDEOS, $DOCUMENTS, $DOWNLOADS, and // Other +/// the other is a unit struct that contains a path of the directory to be red +#[derive(Debug, Clone, Serialize, Deserialize, TS)] +#[ts(export)] +pub(crate) enum Dir { + /// the device home directory + Home, + Pictures, + Videos, + Documents, + Downloads, + Audio, + Desktop, + /// the location the files received are saved + FileSync, + Other(String), +} + +impl Dir { + /// to string + pub fn _to_string(&self) -> String { + match self { + Dir::Home => dirs::home_dir().unwrap().to_str().unwrap().to_string(), + Dir::Pictures => dirs::picture_dir().unwrap().to_str().unwrap().to_string(), + Dir::Videos => dirs::video_dir().unwrap().to_str().unwrap().to_string(), + Dir::Documents => dirs::document_dir().unwrap().to_str().unwrap().to_string(), + Dir::Downloads => dirs::download_dir().unwrap().to_str().unwrap().to_string(), + Dir::Audio => dirs::audio_dir().unwrap().to_str().unwrap().to_string(), + Dir::Desktop => dirs::desktop_dir().unwrap().to_str().unwrap().to_string(), + Dir::FileSync => UPLOAD_PATH.to_string(), + Dir::Other(path) => path.to_string(), + } + } + + // convert to path + pub fn to_path(&self) -> std::path::PathBuf { + match self { + Dir::Home => dirs::home_dir().unwrap(), + Dir::Pictures => dirs::picture_dir().unwrap(), + Dir::Videos => dirs::video_dir().unwrap(), + Dir::Documents => dirs::document_dir().unwrap(), + Dir::Downloads => dirs::download_dir().unwrap(), + Dir::Audio => dirs::audio_dir().unwrap(), + Dir::Desktop => dirs::desktop_dir().unwrap(), + Dir::FileSync => PathBuf::from(UPLOAD_PATH.to_string()), + Dir::Other(path) => PathBuf::from(path), + } + } + + // from string + pub fn from_string(path: &str) -> Self { + match path { + "home" => Dir::Home, + "pictures" => Dir::Pictures, + "videos" => Dir::Videos, + "documents" => Dir::Documents, + "downloads" => Dir::Downloads, + "audio" => Dir::Audio, + "desktop" => Dir::Desktop, + "filesync" => Dir::FileSync, + _ => Dir::Other(path.to_string()), + } + } +} + +/// read directory +#[tauri::command] +pub async fn read_dir(path: &str) -> ApiResponse, ()> { + println!("reading from {path}"); + let path = Dir::from_string(path).to_path(); + let files = get_files_in_directory(&path).await; + if files.is_err() { + return Err(CommandData::err("Error fetching files", ())); + } + + // convert to file type + let mut entries: Vec = Vec::new(); + for entry in files.unwrap() { + let file_path = PathBuf::from(entry); + let file = File::from_path(&file_path); + entries.push(file) + } + + Ok(CommandData::ok("Successfully fetch the data", entries)) +} + +// send file from this server to another +// accept path to file as argument +// validate the file existence +// use streams to upload +// the server id is the port on which the peer node run eg -> 23345 +#[tauri::command(async)] +pub async fn _share_file_with_peer( + file_path: String, + server_id: u16, +) -> Result, CommandData<()>> { + let mut file = tokio::fs::File::open(file_path).await.unwrap(); + let mut vec = Vec::new(); + println!("file content {vec:?}"); + let _ = file.read_to_end(&mut vec).await.unwrap(); + // println!("file content {vec:?}"); + + // file.read_to_end(&mut vec).await.unwrap(); + let client = reqwest::Client::new(); + + // get the IP address of the share network + let my_local_ip = ip_manager::autodetect_ip_address() + .ok() + .unwrap() + // .expect("Invalid Ip address detected") + .parse::() + .unwrap(); + let ip_address = format!("http://{:?}:{:?}/upload", my_local_ip, server_id); + + println!("my client id is {ip_address}"); + let _res = client + .post(&ip_address) + .header("content-type", "application/octet-stream") + .body(vec) + .send() + .await + .unwrap(); + + println!("the response here {_res:?}"); + + // return an instance of the command data + // Ok(CommandData::new("file successfully sent", true, res)) + Ok(CommandData::ok( + "file successfully sent", + json!({ + "success":true, + // data:r + }), + )) + // todo!() +} + +// save file transfer to the database +//TODO: test this +#[tauri::command(async)] +pub async fn _save_file_transfer( + file_path: String, + server_id: u16, +) -> Result, CommandData<()>> { + let mut file = tokio::fs::File::open(file_path).await.unwrap(); + let mut vec = Vec::new(); + println!("file content {vec:?}"); + let _ = file.read_to_end(&mut vec).await.unwrap(); + // println!("file content {vec:?}"); + + // file.read_to_end(&mut vec).await.unwrap(); + let client = reqwest::Client::new(); + + // get the IP address of the share network + let my_local_ip = ip_manager::autodetect_ip_address() + .ok() + .unwrap() + // .expect("Invalid Ip address detected") + .parse::() + .unwrap(); + let ip_address = format!("http://{:?}:{:?}/upload", my_local_ip, server_id); + + println!("my client id is {ip_address}"); + let _res = client + .post(&ip_address) + .header("content-type", "application/octet-stream") + .body(vec) + .send() + .await + .unwrap(); + + println!("the response here {_res:?}"); + + // return an instance of the command data + // Ok(CommandData::new("file successfully sent", true, res)) + Ok(CommandData::ok( + "file successfully sent", + json!({ + "success":true, + // data:r + }), + )) + // todo!() +} + +// save file transfer history +#[tauri::command(async)] +pub async fn _persist_transfer_history( + file: TransferHistoryBuilder, +) -> Result, CommandData<()>> { + // save the file data in the database + let status = database::TransferHistory::new(file).save().await; + if status.is_err() { + return Err(CommandData::err("error saving file transfer history", ())); + } + + Ok(CommandData::ok( + "file transfer history successfully saved", + status.unwrap(), + )) +} + +// get the file transfer history +#[tauri::command(async)] +pub async fn get_transfer_history() -> Result>, CommandData<()>> { + // save the file data in the database + let data = database::TransferHistory::fetch().await; + if data.is_err() { + return Err(CommandData::err("error fetching file transfer history", ())); + } + + Ok(CommandData::ok( + "file transfer history successfully fetched", + data.unwrap(), + )) +} diff --git a/desktop/core/src/file_manager/search.rs b/desktop/core/src/file_manager/search.rs deleted file mode 100644 index 6040347f..00000000 --- a/desktop/core/src/file_manager/search.rs +++ /dev/null @@ -1,157 +0,0 @@ -#![allow(unused_imports)] -use std::path::PathBuf; -use walkdir::{DirEntry, WalkDir}; -use wildmatch::WildMatch; - -use super::file::File; -use crate::utils::{fs::is_hidden, CommandData}; -use assert_fs::prelude::*; - -fn is_wildcard_match(pattern: &str, entry: &DirEntry) -> bool { - let file_name = entry.file_name(); - let file_name = file_name.to_str().unwrap(); - WildMatch::new(pattern).matches(file_name) -} - -// searches all files in the root directory that matches with the wildcard pattern -// ignores hidden files -// ignores any non-accessible files (e.g. permission errors) -pub fn search_files(pattern: &str, root: &PathBuf) -> Vec { - let root_dir = WalkDir::new(root).into_iter(); - - root_dir - .filter_map(|e| e.ok()) - .filter(|e| !is_hidden(e)) - .filter(|e| e.file_type().is_file()) - .filter(|e| is_wildcard_match(pattern, e)) - .map(File::from) - .collect() -} - -#[test] -fn test_search_files_recursive() { - let temp = assert_fs::TempDir::new().unwrap(); - let root = temp.path().to_path_buf(); - - let file1 = temp.child("file1.txt"); - file1.touch().unwrap(); - - let file2 = temp.child("file2.png"); - file2.touch().unwrap(); - - let a = temp.child("a.txt"); - a.touch().unwrap(); - - let dir1 = temp.child("dir1"); - dir1.create_dir_all().unwrap(); - - let file3 = dir1.child("file3.mp4"); - file3.touch().unwrap(); - - let results = search_files("*", &root); - assert_eq!(results.len(), 4); -} - -#[test] -fn test_search_files_hidden_not_included() { - let temp = assert_fs::TempDir::new().unwrap(); - let root = temp.path().to_path_buf(); - - let file1 = temp.child("file1.txt"); - file1.touch().unwrap(); - - let file2 = temp.child(".file2.png"); - file2.touch().unwrap(); - - let results = search_files("*", &root); - assert_eq!(results.len(), 1); - - for file in results { - assert_ne!(file.file_name, ".file2.png"); - } -} - -#[test] -fn test_search_files_with_pattern() { - let temp = assert_fs::TempDir::new().unwrap(); - let root = temp.path().to_path_buf(); - - let file1 = temp.child("file1.txt"); - file1.touch().unwrap(); - - let file2 = temp.child("file2.png"); - file2.touch().unwrap(); - - let results = search_files("*.txt", &root); - assert_eq!(results.len(), 1); - - for file in results { - assert_eq!(file.file_name, "file1.txt"); - } -} - -#[test] -fn test_search_files_with_pattern_recursive() { - let temp = assert_fs::TempDir::new().unwrap(); - let root = temp.path().to_path_buf(); - - let file1 = temp.child("file1.txt"); - file1.touch().unwrap(); - - let file2 = temp.child("file2.png"); - file2.touch().unwrap(); - - let dir1 = temp.child("dir1"); - dir1.create_dir_all().unwrap(); - - let file3 = dir1.child("file3.mp4"); - file3.touch().unwrap(); - - let results = search_files("*.txt", &root); - assert_eq!(results.len(), 1); - - for file in results { - assert_eq!(file.file_name, "file1.txt"); - } -} - -#[test] -fn test_search_files_empty() { - let temp = assert_fs::TempDir::new().unwrap(); - let root = temp.path().to_path_buf(); - - let results = search_files("*", &root); - assert_eq!(results.len(), 0); -} - -#[test] -fn test_search_files_nonexistent_dir() { - let temp = assert_fs::TempDir::new().unwrap(); - let root = temp.path().to_path_buf(); - temp.close().unwrap(); - - let results = search_files("*", &root); - assert_eq!(results.len(), 0); -} - -#[test] -fn test_search_files_with_nonascii_filename() { - let temp = assert_fs::TempDir::new().unwrap(); - let root = temp.path().to_path_buf(); - - let file1 = temp.child("file1.txt"); - file1.touch().unwrap(); - - let file2 = temp.child("file2.png"); - file2.touch().unwrap(); - - let file3 = temp.child("🦀🦀🦀.txt"); - file3.touch().unwrap(); - - let results = search_files("*.txt", &root); - assert_eq!(results.len(), 2); - - for file in results { - assert!(file.file_name == "file1.txt" || file.file_name == "🦀🦀🦀.txt"); - } -} diff --git a/desktop/core/src/ipc_manager/fs.rs b/desktop/core/src/ipc_manager/fs.rs deleted file mode 100644 index 316c385d..00000000 --- a/desktop/core/src/ipc_manager/fs.rs +++ /dev/null @@ -1,232 +0,0 @@ -use std::net::Ipv4Addr; -use std::path::PathBuf; -use crate::UPLOAD_PATH; -use crate::{ - file_manager::file::{get_files_in_directory, File}, - utils::{ApiResponse, CommandData}, -}; -use dirs; -use serde::{Deserialize, Serialize}; -use serde_json::{json, Value}; -use ts_rs::TS; - -use crate::database::{self, TransferHistory, TransferHistoryBuilder}; -use crate::network_manager::ip_manager; -use tokio::io::AsyncReadExt; - -/// the dir enum, reads, $HOME, $PICTURES, $VIDEOS, $DOCUMENTS, $DOWNLOADS, and // Other -/// the other is a unit struct that contains a path of the directory to be red -#[derive(Debug, Clone, Serialize, Deserialize, TS)] -#[ts(export)] -pub(crate) enum Dir { - /// the device home directory - Home, - Pictures, - Videos, - Documents, - Downloads, - Audio, - Desktop, - /// the location the files received are saved - FileSync, - Other(String), -} - -impl Dir { - /// to string - pub fn _to_string(&self) -> String { - match self { - Dir::Home => dirs::home_dir().unwrap().to_str().unwrap().to_string(), - Dir::Pictures => dirs::picture_dir().unwrap().to_str().unwrap().to_string(), - Dir::Videos => dirs::video_dir().unwrap().to_str().unwrap().to_string(), - Dir::Documents => dirs::document_dir().unwrap().to_str().unwrap().to_string(), - Dir::Downloads => dirs::download_dir().unwrap().to_str().unwrap().to_string(), - Dir::Audio => dirs::audio_dir().unwrap().to_str().unwrap().to_string(), - Dir::Desktop => dirs::desktop_dir().unwrap().to_str().unwrap().to_string(), - Dir::FileSync => UPLOAD_PATH.to_string(), - Dir::Other(path) => path.to_string(), - } - } - - // convert to path - pub fn to_path(&self) -> std::path::PathBuf { - match self { - Dir::Home => dirs::home_dir().unwrap(), - Dir::Pictures => dirs::picture_dir().unwrap(), - Dir::Videos => dirs::video_dir().unwrap(), - Dir::Documents => dirs::document_dir().unwrap(), - Dir::Downloads => dirs::download_dir().unwrap(), - Dir::Audio => dirs::audio_dir().unwrap(), - Dir::Desktop => dirs::desktop_dir().unwrap(), - Dir::FileSync => PathBuf::from(UPLOAD_PATH.to_string()), - Dir::Other(path) => PathBuf::from(path), - } - } - - // from string - pub fn from_string(path: &str) -> Self { - match path { - "home" => Dir::Home, - "pictures" => Dir::Pictures, - "videos" => Dir::Videos, - "documents" => Dir::Documents, - "downloads" => Dir::Downloads, - "audio" => Dir::Audio, - "desktop" => Dir::Desktop, - "filesync" => Dir::FileSync, - _ => Dir::Other(path.to_string()), - } - } -} - -/// read directory -#[tauri::command] -pub async fn read_dir(path: &str) -> ApiResponse, ()> { - println!("reading from {path}"); - let path = Dir::from_string(path).to_path(); - let files = get_files_in_directory(&path).await; - if files.is_err() { - return Err(CommandData::err("Error fetching files", ())); - } - - // convert to file type - let mut entries: Vec = Vec::new(); - for entry in files.unwrap() { - let file_path = PathBuf::from(entry); - let file = File::from_path(&file_path); - entries.push(file) - } - - Ok(CommandData::ok("Successfully fetch the data", entries)) -} - -// send file from this server to another -// accept path to file as argument -// validate the file existence -// use streams to upload -// the server id is the port on which the peer node run eg -> 23345 -#[tauri::command(async)] -pub async fn _share_file_with_peer( - file_path: String, - server_id: u16, -) -> Result, CommandData<()>> { - let mut file = tokio::fs::File::open(file_path).await.unwrap(); - let mut vec = Vec::new(); - println!("file content {vec:?}"); - let _ = file.read_to_end(&mut vec).await.unwrap(); - // println!("file content {vec:?}"); - - // file.read_to_end(&mut vec).await.unwrap(); - let client = reqwest::Client::new(); - - // get the IP address of the share network - let my_local_ip = ip_manager::autodetect_ip_address() - .ok() - .unwrap() - // .expect("Invalid Ip address detected") - .parse::() - .unwrap(); - let ip_address = format!("http://{:?}:{:?}/upload", my_local_ip, server_id); - - println!("my client id is {ip_address}"); - let _res = client - .post(&ip_address) - .header("content-type", "application/octet-stream") - .body(vec) - .send() - .await - .unwrap(); - - println!("the response here {_res:?}"); - - // return an instance of the command data - // Ok(CommandData::new("file successfully sent", true, res)) - Ok(CommandData::ok( - "file successfully sent", - json!({ - "success":true, - // data:r - }), - )) - // todo!() -} - -// save file transfer to the database -//TODO: test this -#[tauri::command(async)] -pub async fn _save_file_transfer( - file_path: String, - server_id: u16, -) -> Result, CommandData<()>> { - let mut file = tokio::fs::File::open(file_path).await.unwrap(); - let mut vec = Vec::new(); - println!("file content {vec:?}"); - let _ = file.read_to_end(&mut vec).await.unwrap(); - // println!("file content {vec:?}"); - - // file.read_to_end(&mut vec).await.unwrap(); - let client = reqwest::Client::new(); - - // get the IP address of the share network - let my_local_ip = ip_manager::autodetect_ip_address() - .ok() - .unwrap() - // .expect("Invalid Ip address detected") - .parse::() - .unwrap(); - let ip_address = format!("http://{:?}:{:?}/upload", my_local_ip, server_id); - - println!("my client id is {ip_address}"); - let _res = client - .post(&ip_address) - .header("content-type", "application/octet-stream") - .body(vec) - .send() - .await - .unwrap(); - - println!("the response here {_res:?}"); - - // return an instance of the command data - // Ok(CommandData::new("file successfully sent", true, res)) - Ok(CommandData::ok( - "file successfully sent", - json!({ - "success":true, - // data:r - }), - )) - // todo!() -} - -// save file transfer history -#[tauri::command(async)] -pub async fn _persist_transfer_history( - file: TransferHistoryBuilder, -) -> Result, CommandData<()>> { - // save the file data in the database - let status = database::TransferHistory::new(file).save().await; - if status.is_err() { - return Err(CommandData::err("error saving file transfer history", ())); - } - - Ok(CommandData::ok( - "file transfer history successfully saved", - status.unwrap(), - )) -} - -// get the file transfer history -#[tauri::command(async)] -pub async fn get_transfer_history() -> Result>, CommandData<()>> { - // save the file data in the database - let data = database::TransferHistory::fetch().await; - if data.is_err() { - return Err(CommandData::err("error fetching file transfer history", ())); - } - - Ok(CommandData::ok( - "file transfer history successfully fetched", - data.unwrap(), - )) -} diff --git a/desktop/core/src/ipc_manager/mod.rs b/desktop/core/src/ipc_manager/mod.rs index 70acb7f0..f1fef474 100644 --- a/desktop/core/src/ipc_manager/mod.rs +++ b/desktop/core/src/ipc_manager/mod.rs @@ -1,5 +1,4 @@ -#[path = "fs.rs"] -pub mod fs_api; + pub mod settings; pub mod utils; pub mod wifi; diff --git a/desktop/core/src/main.rs b/desktop/core/src/main.rs index d66cb638..97c30559 100644 --- a/desktop/core/src/main.rs +++ b/desktop/core/src/main.rs @@ -2,16 +2,14 @@ #![cfg_attr(not(debug_assertions), windows_subsystem = "windows")] extern crate uptime_lib; - -use crate::ipc_manager::fs_api::get_transfer_history; -use crate::ipc_manager::fs_api::read_dir; +use crate::file_manager::read_dir; use crate::ipc_manager::settings::{get_application_data, get_settings, update_settings}; use crate::ipc_manager::utils::{ generate_qr_code, get_ip_address, get_system_information, is_connected_to_wifi, }; use lazy_static::lazy_static; use server::http_server; - +use crate::file_manager::get_transfer_history; mod database; mod file_manager; mod ipc_manager; diff --git a/desktop/core/src/network_manager/mod.rs b/desktop/core/src/network_manager/mod.rs index 45778ae3..71135721 100644 --- a/desktop/core/src/network_manager/mod.rs +++ b/desktop/core/src/network_manager/mod.rs @@ -1,3 +1,5 @@ +#[allow(unused)] + use std::fmt; use crate::utils::system_info::SystemInformation; @@ -36,7 +38,10 @@ pub enum NetworkAccessStatus { Error, } +#[allow(unused)] + impl WifiHotspotConfig { + pub fn new(gateway: &str) -> Self { let SystemInformation { system_name: ssid, .. diff --git a/desktop/core/src/server/routes.rs b/desktop/core/src/server/routes.rs index 07c09876..99fdc479 100644 --- a/desktop/core/src/server/routes.rs +++ b/desktop/core/src/server/routes.rs @@ -65,6 +65,7 @@ pub async fn system_information() -> (StatusCode, Json Html<&'static str> { Html( r#" diff --git a/desktop/core/src/utils/fs.rs b/desktop/core/src/utils/fs.rs deleted file mode 100644 index 051b0d06..00000000 --- a/desktop/core/src/utils/fs.rs +++ /dev/null @@ -1,96 +0,0 @@ -use sysinfo::{DiskExt, SystemExt}; -// pub mod storage_information; -/// a function to compute file size -/// accept files size in byte and parse it to human readable KB, MB, TB, GB e.t.c -pub fn compute_file_size(size: u128) -> String { - if size > (1024 * 1024 * 1024 * 1024) { - format!("{:.2} TB", size / (1024 * 1024 * 1024 * 1024)) - } else if size > (1024 * 1024 * 1024) { - format!("{:.2} GB", size / (1024 * 1024 * 1024)) - } else if size > (1024 * 1024) { - format!("{:.2} MB", size / (1024 * 1024)) - } else if size > 1024 { - format!("{:.2} KB", size / (1024)) - } else { - format!("{:.2} B", size) - } -} - -/// see if file is a dot file eg .cache .yarn -/// ignore if true -pub fn is_hidden(entry: &walkdir::DirEntry) -> bool { - entry - .file_name() - .to_str() - .map(|s| s.starts_with('.')) - .unwrap_or(false) -} - -#[derive(serde::Serialize, Debug)] -pub struct DriveInformation { - name: String, - mount_point: String, - total_space: u64, - available_space: u64, - is_removable: bool, - disk_type: String, - file_system: String, -} - -#[derive(serde::Serialize)] -pub struct Drives { - array_of_drives: Vec, -} - -// #[tauri::command] -// pub fn get_drives() -> Result { -// let array_of_drives = System::new_all() -// .disks() -// .iter() -// .map(|disk| { -// let mut total_space = disk.total_space(); -// let available_space = disk.available_space(); -// let mount_point = disk.mount_point().to_str().unwrap_or("/").to_string(); -// let name = disk.name().to_str().unwrap_or("Disk").to_string(); -// let is_removable = disk.is_removable(); -// let mut caption = mount_point.clone(); -// caption.pop(); -// let file_system = String::from_utf8(disk.file_system().to_vec()) -// .unwrap_or_else(|_| "Err".to_string()); -// let disk_type = match disk.type_() { -// sysinfo::DiskType::SSD => "SSD".to_string(), -// sysinfo::DiskType::HDD => "HDD".to_string(), -// _ => "Removable Disk".to_string(), -// }; - -// if total_space < available_space && cfg!(target_os = "windows") { -// let wmic_process = Command::new("cmd") -// .args([ -// "/C", -// &format!("wmic logical disk where Caption='{caption}' get Size"), -// ]) -// .output() -// .expect("failed to execute process"); -// let wmic_process_output = String::from_utf8(wmic_process.stdout).unwrap(); -// let parsed_size = -// wmic_process_output.split("\r\r\n").collect::>()[1].to_string(); - -// if let Ok(n) = parsed_size.trim().parse::() { -// total_space = n; -// } -// } - -// DriveInformation { -// name, -// mount_point, -// total_space, -// available_space, -// is_removable, -// disk_type, -// file_system, -// } -// }) -// .collect(); - -// Ok(Drives { array_of_drives }) -// } diff --git a/desktop/core/src/utils/mod.rs b/desktop/core/src/utils/mod.rs index 8205d739..92bbb208 100644 --- a/desktop/core/src/utils/mod.rs +++ b/desktop/core/src/utils/mod.rs @@ -1,12 +1,11 @@ use rand::Rng; use serde::{Deserialize, Serialize}; -use sha2::{Digest, Sha256}; use std::fmt::{self}; use std::fs::File; use std::path::{Path, PathBuf}; use ts_rs::TS; -pub mod fs; +// pub mod fs; pub mod shell; pub mod system_info; /// data structure of response to return from Tauri Core @@ -69,8 +68,7 @@ impl CommandData { } /// Checks whether given path is a file that can be opened. -/// -/// Returns error if no. +/// Returns error if not pub fn _verify_file_openable(file: &PathBuf) -> Result<(), String> { File::open(Path::new(&file)) .map_err(|err| format!("Error: Cannot open {:?}: {}", file, err))?; @@ -83,9 +81,11 @@ pub fn _verify_file_openable(file: &PathBuf) -> Result<(), String> { Ok(()) } -pub fn generate_password() -> String { + +/// generate password fro wifi hotspot +pub fn _generate_password() -> String { let mut rng = rand::thread_rng(); - let chars: Vec = "23456789abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ" + let chars: Vec = "0123456789abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ" .chars() .collect(); const PASSWORD_LENGTH: usize = 8; @@ -97,27 +97,6 @@ pub fn generate_password() -> String { String::from_iter(password) } -pub fn hash_file(filename: &Path) -> Result, Box> { - let mut file = std::fs::File::open(filename)?; - let mut hasher = Sha256::new(); - std::io::copy(&mut file, &mut hasher)?; - Ok(hasher.finalize().to_vec()) -} -pub fn expand_dir(dir: PathBuf) -> (Vec, Vec) { - let mut files_found = vec![]; - let mut dirs_to_search = vec![]; - if let Ok(entries) = std::fs::read_dir(&dir) { - for entry in entries.filter_map(|e| e.ok()) { - if let Ok(metadata) = entry.metadata() { - if metadata.is_dir() { - dirs_to_search.push(entry.path()); - } - if metadata.is_file() { - files_found.push(entry.path().to_string_lossy().to_string()); - } - } - } - } - (files_found, dirs_to_search) -} + + diff --git a/desktop/core/src/utils/shell.rs b/desktop/core/src/utils/shell.rs index 975c145c..01834efd 100644 --- a/desktop/core/src/utils/shell.rs +++ b/desktop/core/src/utils/shell.rs @@ -1,3 +1,4 @@ +#[allow(unused)] pub fn execute_shell_command(command: &str) -> std::io::Result { let mut cmd = std::process::Command::new("sh") .arg("-c") diff --git a/desktop/core/src/utils/system_info.rs b/desktop/core/src/utils/system_info.rs index 6edaef74..45c9979b 100644 --- a/desktop/core/src/utils/system_info.rs +++ b/desktop/core/src/utils/system_info.rs @@ -10,11 +10,11 @@ use std::collections::HashSet; use sys_info; use sysinfo::{DiskExt, System, SystemExt}; use ts_rs::TS; - + use crate::file_manager::file::compute_file_size; use crate::network_manager::ip_manager; use crate::SERVER_PORT; -use super::fs::compute_file_size; + #[derive(Debug, Deserialize, Serialize, Clone, TS)] #[ts(export)] diff --git a/desktop/core/tauri.conf.json b/desktop/core/tauri.conf.json index 0bb653cd..3d199917 100644 --- a/desktop/core/tauri.conf.json +++ b/desktop/core/tauri.conf.json @@ -8,7 +8,7 @@ }, "package": { "productName": "filesync", - "version": "0.7.5" + "version": "0.7.6" }, "tauri": { "allowlist": { @@ -16,6 +16,10 @@ "window": { "all": true }, + "clipboard": { + + "writeText": true + }, "app": { "all": true, "hide": true, diff --git a/desktop/package.json b/desktop/package.json index 86757510..56748c37 100644 --- a/desktop/package.json +++ b/desktop/package.json @@ -14,6 +14,7 @@ "lint": "next lint" }, "dependencies": { + "@ant-design/icons": "^5.3.7", "@cyntler/react-doc-viewer": "^1.14.1", "@headlessui/react": "^1.7.13", "@heroicons/react": "^2.0.16", @@ -27,10 +28,12 @@ "react-dom": "^18.2.0", "react-file-viewer": "^1.2.1", "react-files-preview": "^2.4.0", + "react-icons": "^5.2.1", "react-identicon": "^1.0.2", "react-identicons": "^1.2.5", "react-qr-code": "^2.0.11", "react-router-dom": "^6.9.0", + "remixicon": "^4.2.0", "tauri-plugin-sqlite-api": "github:lzdyes/tauri-plugin-sqlite#v0.1.1", "tauri-plugin-store-api": "https://github.com/tauri-apps/tauri-plugin-store#v1", "viewerjs": "^1.11.6" diff --git a/desktop/src/components/MediaViewer/index.tsx b/desktop/src/components/MediaViewer/index.tsx new file mode 100644 index 00000000..ded767dc --- /dev/null +++ b/desktop/src/components/MediaViewer/index.tsx @@ -0,0 +1,7 @@ +import React from 'react' + +export default function MediaViewer() { + return ( +
MediaViewer
+ ) +} diff --git a/desktop/src/components/nav/index.tsx b/desktop/src/components/nav/index.tsx index 0a37724e..bc852658 100644 --- a/desktop/src/components/nav/index.tsx +++ b/desktop/src/components/nav/index.tsx @@ -38,7 +38,7 @@ export default function Navigation() { }, { icon: , - name: "QR Connection", + name: "Connect Device", alternateIcon: , path: "/connection", }, @@ -48,18 +48,19 @@ export default function Navigation() { name: "Share files", alternateIcon: , }, - { - path: "/history", - icon: , - name: "Transfer History", - alternateIcon: , - }, + { path: "/received", icon: , name: "Received files", alternateIcon: , }, + { + path: "/history", + icon: , + name: "Transfer History", + alternateIcon: , + }, { path: "/settings", icon: , diff --git a/desktop/yarn.lock b/desktop/yarn.lock index 7a1738d9..c52d23ac 100644 --- a/desktop/yarn.lock +++ b/desktop/yarn.lock @@ -51,6 +51,17 @@ classnames "^2.2.6" rc-util "^5.31.1" +"@ant-design/icons@^5.3.7": + version "5.3.7" + resolved "https://registry.yarnpkg.com/@ant-design/icons/-/icons-5.3.7.tgz#d9f3654bf7934ee5faba43f91b5a187f5309ec68" + integrity sha512-bCPXTAg66f5bdccM4TT21SQBDO1Ek2gho9h3nO9DAKXJP4sq+5VBjrQMSxMVXSB3HyEz+cUbHQ5+6ogxCOpaew== + dependencies: + "@ant-design/colors" "^7.0.0" + "@ant-design/icons-svg" "^4.4.0" + "@babel/runtime" "^7.11.2" + classnames "^2.2.6" + rc-util "^5.31.1" + "@ant-design/react-slick@~1.1.2": version "1.1.2" resolved "https://registry.yarnpkg.com/@ant-design/react-slick/-/react-slick-1.1.2.tgz#f84ce3e4d0dc941f02b16f1d1d6d7a371ffbb4f1" @@ -4035,6 +4046,11 @@ react-files-preview@^2.4.0: dependencies: react-photo-editor "^1.2.0" +react-icons@^5.2.1: + version "5.2.1" + resolved "https://registry.yarnpkg.com/react-icons/-/react-icons-5.2.1.tgz#28c2040917b2a2eda639b0f797bff1888e018e4a" + integrity sha512-zdbW5GstTzXaVKvGSyTaBalt7HSfuK5ovrzlpyiWHAFXndXTdd/1hdDHI4xBM1Mn7YriT6aqESucFl9kEXzrdw== + react-identicon@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/react-identicon/-/react-identicon-1.0.2.tgz#79ee46541e3665c873733b113496e71ea6a87264" @@ -4191,6 +4207,11 @@ regexp.prototype.flags@^1.5.2: es-errors "^1.3.0" set-function-name "^2.0.1" +remixicon@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/remixicon/-/remixicon-4.2.0.tgz#2df60b1764b11bb363f796b827ed8e03eab031c4" + integrity sha512-MF5wApNveRh3n0iMVM+lr2nSWrj/rBbSD2eWapuD9ReYRGs5naAUR1BqVBCHGqm286FIS6zwwmUf96QjHQ9l4w== + reselect@^4.1.6: version "4.1.8" resolved "https://registry.yarnpkg.com/reselect/-/reselect-4.1.8.tgz#3f5dc671ea168dccdeb3e141236f69f02eaec524"