diff --git a/apps/desktop/src-tauri/src/commands.rs b/apps/desktop/src-tauri/src/commands.rs index ceb2bee83..b94364789 100644 --- a/apps/desktop/src-tauri/src/commands.rs +++ b/apps/desktop/src-tauri/src/commands.rs @@ -1,58 +1,58 @@ -// DEPRECATE EVERYTHING IN THIS FILE -use anyhow::Result; -use sdcorelib::{ - file::{indexer, retrieve, retrieve::Directory, watcher::watch_dir}, - state::{client, client::ClientState}, - sys, - sys::{volumes, volumes::Volume}, -}; -#[tauri::command(async)] -pub async fn scan_dir(path: String) -> Result<(), String> { - let files = indexer::scan(&path).await.map_err(|e| e.to_string()); +// // DEPRECATE EVERYTHING IN THIS FILE +// use anyhow::Result; +// use sdcorelib::{ +// file::{indexer, retrieve, retrieve::Directory, watcher::watch_dir}, +// state::{client, client::ClientState}, +// sys, +// sys::{volumes, volumes::Volume}, +// }; +// #[tauri::command(async)] +// pub async fn scan_dir(path: String) -> Result<(), String> { +// let files = indexer::scan(&path).await.map_err(|e| e.to_string()); - println!("file: {:?}", files); +// println!("file: {:?}", files); - Ok(()) -} +// Ok(()) +// } -#[tauri::command(async)] -pub async fn get_files(path: String) -> Result { - Ok( - retrieve::get_dir_with_contents(&path) - .await - .map_err(|e| e.to_string())?, - ) -} +// #[tauri::command(async)] +// pub async fn get_files(path: String) -> Result { +// Ok( +// retrieve::get_dir_with_contents(&path) +// .await +// .map_err(|e| e.to_string())?, +// ) +// } -#[tauri::command] -pub fn get_config() -> ClientState { - client::get() -} +// #[tauri::command] +// pub fn get_config() -> ClientState { +// client::get() +// } -#[tauri::command] -pub fn get_mounts() -> Result, String> { - Ok(volumes::get().unwrap()) -} +// #[tauri::command] +// pub fn get_mounts() -> Result, String> { +// Ok(volumes::get().unwrap()) +// } -#[tauri::command(async)] -pub async fn test_scan() -> Result<(), String> { - Ok( - indexer::test_scan("/Users/jamie") - .await - .map_err(|e| e.to_string())?, - ) -} +// #[tauri::command(async)] +// pub async fn test_scan() -> Result<(), String> { +// Ok( +// indexer::test_scan("/Users/jamie") +// .await +// .map_err(|e| e.to_string())?, +// ) +// } -#[tauri::command] -pub async fn start_watcher(path: &str) -> Result<(), String> { - println!("starting watcher for: {:?}", path); - watch_dir(&path); +// #[tauri::command] +// pub async fn start_watcher(path: &str) -> Result<(), String> { +// println!("starting watcher for: {:?}", path); +// watch_dir(&path); - Ok(()) -} +// Ok(()) +// } -#[tauri::command] -pub async fn create_location(path: &str) -> Result<(), String> { - let _location = sys::locations::create_location(path); - Ok(()) -} +// #[tauri::command] +// pub async fn create_location(path: &str) -> Result<(), String> { +// let _location = sys::locations::create_location(path); +// Ok(()) +// } diff --git a/apps/desktop/src-tauri/src/main.rs b/apps/desktop/src-tauri/src/main.rs index 4684e1dfb..5aa916dfd 100644 --- a/apps/desktop/src-tauri/src/main.rs +++ b/apps/desktop/src-tauri/src/main.rs @@ -2,7 +2,7 @@ use sdcorelib::{ClientCommand, ClientQuery, Core, CoreResponse}; use tauri::api::path; use tauri::Manager; // use tauri_plugin_shadows::Shadows; -mod commands; +// mod commands; mod menu; #[tauri::command(async)] @@ -50,13 +50,13 @@ async fn main() { client_query_transport, client_command_transport, // deprecate below - commands::scan_dir, - commands::create_location, - commands::get_files, - commands::get_config, - commands::get_mounts, - commands::test_scan, - commands::start_watcher, + // commands::scan_dir, + // commands::create_location, + // commands::get_files, + // commands::get_config, + // commands::get_mounts, + // commands::test_scan, + // commands::start_watcher, ]) .menu(menu::get_menu()) .run(tauri::generate_context!()) diff --git a/apps/desktop/src/components/file/Sidebar.tsx b/apps/desktop/src/components/file/Sidebar.tsx index 825419d54..e9822da5d 100644 --- a/apps/desktop/src/components/file/Sidebar.tsx +++ b/apps/desktop/src/components/file/Sidebar.tsx @@ -10,6 +10,7 @@ import { Button } from '../primitive'; import { Dropdown } from '../primitive/Dropdown'; import { DefaultProps } from '../primitive/types'; import { useBridgeQuery } from '@sd/state'; + interface SidebarProps extends DefaultProps {} export const SidebarLink = (props: NavLinkProps) => ( diff --git a/packages/core/src/crypto/encryption.rs b/packages/core/src/crypto/encryption.rs index 52f6713db..12b7a1570 100644 --- a/packages/core/src/crypto/encryption.rs +++ b/packages/core/src/crypto/encryption.rs @@ -2,7 +2,8 @@ use serde::{Deserialize, Serialize}; use ts_rs::TS; #[derive(Serialize, Deserialize, Clone, Debug, TS)] -pub enum Encryption { +#[ts(export)] +pub enum EncryptionAlgorithm { None = 0, AES128, AES192, diff --git a/packages/core/src/file/retrieve.rs b/packages/core/src/file/explorer/mod.rs similarity index 89% rename from packages/core/src/file/retrieve.rs rename to packages/core/src/file/explorer/mod.rs index 8dccf49ae..a5f129ca3 100644 --- a/packages/core/src/file/retrieve.rs +++ b/packages/core/src/file/explorer/mod.rs @@ -12,7 +12,7 @@ pub struct Directory { pub contents: Vec, } -pub async fn get_dir_with_contents(path: &str) -> Result { +pub async fn open_dir(path: &str) -> Result { let db = db::get().await?; println!("getting files... {:?}", &path); diff --git a/packages/core/src/file/indexer.rs b/packages/core/src/file/indexer.rs index f28f187de..c388fd906 100644 --- a/packages/core/src/file/indexer.rs +++ b/packages/core/src/file/indexer.rs @@ -10,12 +10,12 @@ use crate::db; use crate::sys::locations::{create_location, get_location, LocationResource}; use crate::util::time; -pub async fn scan_paths(location_id: i64) -> Result<()> { +pub async fn scan_loc(location_id: i64) -> Result<()> { // get location by location_id from db and include location_paths let location = get_location(location_id).await?; if let Some(path) = &location.path { - scan(path).await?; + scan_path(path).await?; watch_dir(path); } @@ -23,7 +23,7 @@ pub async fn scan_paths(location_id: i64) -> Result<()> { } // creates a vector of valid path buffers from a directory -pub async fn scan(path: &str) -> Result<()> { +pub async fn scan_path(path: &str) -> Result<()> { println!("Scanning directory: {}", &path); // let current_library = library::loader::get().await?; diff --git a/packages/core/src/file/mod.rs b/packages/core/src/file/mod.rs index 2718001fe..cb9edd542 100644 --- a/packages/core/src/file/mod.rs +++ b/packages/core/src/file/mod.rs @@ -4,8 +4,8 @@ use ts_rs::TS; use crate::{db, prisma::FileData, sys::locations::LocationResource}; pub mod checksum; +pub mod explorer; pub mod indexer; -pub mod retrieve; pub mod thumb; pub mod watcher; diff --git a/packages/core/src/job/create.rs b/packages/core/src/job/create.rs deleted file mode 100644 index 1b4ed05b1..000000000 --- a/packages/core/src/job/create.rs +++ /dev/null @@ -1,9 +0,0 @@ -use db::entity; - -struct QueueItem { - job: entity::job::Model, -} - -pub async fn queue() { - -} \ No newline at end of file diff --git a/packages/core/src/job/mod.rs b/packages/core/src/job/mod.rs index 5f07af7cc..0265a1d88 100644 --- a/packages/core/src/job/mod.rs +++ b/packages/core/src/job/mod.rs @@ -1 +1,122 @@ -pub mod jobs; +use crate::{ + db::get, + prisma::{Client, Job, JobData}, + ClientQuery, Core, CoreEvent, +}; +use anyhow::Result; +use int_enum::IntEnum; +use serde::{Deserialize, Serialize}; +use ts_rs::TS; + +#[derive(Debug, Clone, Serialize, Deserialize, TS)] +#[ts(export)] +pub struct JobResource { + pub id: i64, + pub client_id: i64, + pub action: JobAction, + pub status: JobStatus, + pub percentage_complete: i64, + pub task_count: i64, + pub completed_task_count: i64, + #[ts(type = "string")] + pub date_created: chrono::DateTime, + #[ts(type = "string")] + pub date_modified: chrono::DateTime, +} + +#[repr(i64)] +#[derive(Debug, Clone, Copy, Serialize, Deserialize, TS, Eq, PartialEq, IntEnum)] +#[ts(export)] +pub enum JobAction { + ScanLoc = 0, + GeneratePreviewMedia = 1, +} + +#[repr(i64)] +#[derive(Debug, Clone, Copy, Serialize, Deserialize, TS, Eq, PartialEq, IntEnum)] +#[ts(export)] +pub enum JobStatus { + Queued = 0, + Running = 1, + Completed = 2, + Canceled = 3, +} + +// convert database struct into a resource struct +impl Into for JobData { + fn into(self) -> JobResource { + JobResource { + id: self.id, + client_id: self.client_id, + action: JobAction::from_int(self.action).unwrap(), + status: JobStatus::from_int(self.status).unwrap(), + percentage_complete: self.percentage_complete, + task_count: self.task_count, + completed_task_count: self.completed_task_count, + date_created: self.date_created, + date_modified: self.date_modified, + } + } +} + +impl JobResource { + pub async fn new(core: &Core, action: JobAction, task_count: i64) -> Result { + let db = get().await?; + let client = db + .client() + .find_unique(Client::uuid().equals(core.state.client_id.clone())) + .exec() + .await + .unwrap(); + + let job = Self { + id: 0, + client_id: client.id, + action, + status: JobStatus::Queued, + percentage_complete: 0, + task_count, + completed_task_count: 0, + date_created: chrono::Utc::now(), + date_modified: chrono::Utc::now(), + }; + + db.job().create_one( + Job::action().set(job.action.int_value()), + Job::clients().link(Client::id().equals(client.id)), + vec![], + ); + + Ok(job) + } + + pub async fn update_task_count(&mut self, core: &Core, completed_task_count: i64) -> Result { + let db = get().await.unwrap(); + db.job() + .find_unique(Job::id().equals(self.id)) + .update(vec![Job::completed_task_count().set(completed_task_count)]) + .exec() + .await; + + self.completed_task_count = completed_task_count; + + core.send(CoreEvent::InvalidateQuery(ClientQuery::JobGetRunning)).await; + + Ok(self.clone()) + } + + pub async fn update_status(&mut self, core: &Core, status: JobStatus) -> Result { + let db = get().await.unwrap(); + db.job() + .find_unique(Job::id().equals(self.id)) + .update(vec![Job::status().set(status.int_value())]) + .exec() + .await; + + self.status = status; + + core.send(CoreEvent::InvalidateQuery(ClientQuery::JobGetRunning)).await; + + Ok(self.clone()) + } +} diff --git a/packages/core/src/lib.rs b/packages/core/src/lib.rs index d0d7e64ef..22deac471 100644 --- a/packages/core/src/lib.rs +++ b/packages/core/src/lib.rs @@ -1,4 +1,5 @@ use anyhow::Result; +use crypto::encryption::EncryptionAlgorithm; use log::{error, info}; use serde::{Deserialize, Serialize}; use state::client::ClientState; @@ -12,6 +13,7 @@ pub mod client; pub mod crypto; pub mod db; pub mod file; +pub mod job; pub mod library; pub mod p2p; pub mod prisma; @@ -72,36 +74,39 @@ impl Core { pub async fn command(&self, cmd: ClientCommand) -> Result { info!("Core command: {:?}", cmd); Ok(match cmd { + // CRUD for locations + ClientCommand::LocCreate { id } => todo!(), + ClientCommand::LocUpdate { id: _, name: _ } => todo!(), + ClientCommand::LocDelete { id: _ } => todo!(), // CRUD for files ClientCommand::FileRead { id: _ } => todo!(), + ClientCommand::FileEncrypt { id: _, algorithm: _ } => todo!(), ClientCommand::FileDelete { id: _ } => todo!(), // CRUD for tags ClientCommand::TagCreate { name: _, color: _ } => todo!(), ClientCommand::TagAssign { file_id: _, tag_id: _ } => todo!(), ClientCommand::TagDelete { id: _ } => todo!(), - // scan the contents of a location on the local filesystem - ClientCommand::LocScan { id: _ } => todo!(), - // CRUD for locations - ClientCommand::LocUpdate { id: _, name: _ } => todo!(), - ClientCommand::LocDelete { id: _ } => todo!(), // CRUD for libraries ClientCommand::SysVolumeUnmount { id: _ } => todo!(), ClientCommand::LibDelete { id: _ } => todo!(), + ClientCommand::TagUpdate { name, color } => todo!(), }) } // query sources of data pub async fn query(&self, query: ClientQuery) -> Result { info!("Core query: {:?}", query); Ok(match query { - // get system volumes without saving to library - ClientQuery::SysGetVolumes => CoreResponse::SysGetVolumes(sys::volumes::get()?), - // get location from library - ClientQuery::SysGetLocation { id } => CoreResponse::SysGetLocations(sys::locations::get_location(id).await?), - // return contents of a directory for the explorer - ClientQuery::LibGetExplorerDir { path, limit: _ } => CoreResponse::LibGetExplorerDir(file::retrieve::get_dir_with_contents(&path).await?), // return the client state from memory ClientQuery::ClientGetState => CoreResponse::ClientGetState(self.state.clone()), + // get system volumes without saving to library + ClientQuery::SysGetVolumes => CoreResponse::SysGetVolumes(sys::volumes::get_volumes()?), + // get location from library + ClientQuery::SysGetLocation { id } => CoreResponse::SysGetLocation(sys::locations::get_location(id).await?), + // return contents of a directory for the explorer + ClientQuery::LibGetExplorerDir { path, limit: _ } => CoreResponse::LibGetExplorerDir(file::explorer::open_dir(&path).await?), ClientQuery::LibGetTags => todo!(), + ClientQuery::JobGetRunning => todo!(), + ClientQuery::JobGetHistory => todo!(), }) } // send an event to the client @@ -118,17 +123,19 @@ impl Core { pub enum ClientCommand { // Files FileRead { id: i64 }, + FileEncrypt { id: i64, algorithm: EncryptionAlgorithm }, FileDelete { id: i64 }, // Library LibDelete { id: i64 }, // Tags TagCreate { name: String, color: String }, + TagUpdate { name: String, color: String }, TagAssign { file_id: i64, tag_id: i64 }, TagDelete { id: i64 }, // Locations - LocScan { id: i64 }, - LocDelete { id: i64 }, + LocCreate { id: i64 }, LocUpdate { id: i64, name: Option }, + LocDelete { id: i64 }, // System SysVolumeUnmount { id: i64 }, } @@ -141,6 +148,8 @@ pub enum ClientQuery { ClientGetState, SysGetVolumes, LibGetTags, + JobGetRunning, + JobGetHistory, SysGetLocation { id: i64 }, LibGetExplorerDir { path: String, limit: i64 }, } @@ -161,11 +170,14 @@ pub enum CoreEvent { #[serde(tag = "key", content = "data")] #[ts(export)] pub enum CoreResponse { - Success, + Success(()), SysGetVolumes(Vec), - SysGetLocations(sys::locations::LocationResource), - LibGetExplorerDir(file::retrieve::Directory), + SysGetLocation(sys::locations::LocationResource), + LibGetExplorerDir(file::explorer::Directory), ClientGetState(ClientState), + LocCreate(sys::locations::LocationResource), + JobGetRunning(Vec), + JobGetHistory(Vec), } #[derive(Error, Debug)] diff --git a/packages/core/src/sys/locations.rs b/packages/core/src/sys/locations.rs index cb0e669c8..714e79177 100644 --- a/packages/core/src/sys/locations.rs +++ b/packages/core/src/sys/locations.rs @@ -104,7 +104,7 @@ pub async fn create_location(path: &str) -> Result { let uuid = uuid::Uuid::new_v4(); // create new location let create_location_params = { - let volumes = match volumes::get() { + let volumes = match volumes::get_volumes() { Ok(volumes) => volumes, Err(e) => Err(LocationError::VolumeReadError(e.to_string()))?, }; diff --git a/packages/core/src/sys/volumes.rs b/packages/core/src/sys/volumes.rs index 813def982..1b22d132e 100644 --- a/packages/core/src/sys/volumes.rs +++ b/packages/core/src/sys/volumes.rs @@ -23,13 +23,7 @@ pub struct Volume { pub is_root_filesystem: bool, } -pub fn get() -> Result, SysError> { - // #[cfg(target_os = "macos")] - // let volumes = native::methods::get_mounts(); - - // return Err(SysError::VolumeError(String::from("Not implemented"))); - - // #[cfg(not(target_os = "macos"))] +pub fn get_volumes() -> Result, SysError> { let all_volumes: Vec = System::new_all() .disks() .iter() @@ -91,7 +85,7 @@ pub fn get() -> Result, SysError> { #[test] fn test_get_volumes() { - let volumes = get().unwrap(); + let volumes = get_volumes().unwrap(); dbg!(&volumes); assert!(volumes.len() > 0); }