From 852ab87b0b1aeb4cd4ba1c42d712c763063f5e93 Mon Sep 17 00:00:00 2001 From: Iaphetes Date: Sun, 16 Mar 2025 19:04:14 +0100 Subject: [PATCH] adding files to database works --- src-tauri/Cargo.lock | 17 ++++ src-tauri/Cargo.toml | 1 + src-tauri/src/database.rs | 162 ++++++++++++++++++++++++++----------- src-tauri/src/file_tree.rs | 26 ++++-- 4 files changed, 154 insertions(+), 52 deletions(-) diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index 57c6e25..cffc3f8 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -165,6 +165,7 @@ dependencies = [ "comrak", "confy", "diff-match-patch-rs", + "futures", "fuzzy-matcher", "html_tag", "rand 0.9.0", @@ -1429,6 +1430,21 @@ dependencies = [ "new_debug_unreachable", ] +[[package]] +name = "futures" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876" +dependencies = [ + "futures-channel", + "futures-core", + "futures-executor", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", +] + [[package]] name = "futures-channel" version = "0.3.31" @@ -1515,6 +1531,7 @@ version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" dependencies = [ + "futures-channel", "futures-core", "futures-io", "futures-macro", diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index f3dbc06..957ac15 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -35,5 +35,6 @@ confy = "0.6.1" tauri-plugin-dialog = "2" diff-match-patch-rs = "0.4.1" rand = "0.9" +futures = "0.3.31" # [profile.dev] # codegen-backend = "cranelift" diff --git a/src-tauri/src/database.rs b/src-tauri/src/database.rs index 8a27ed1..d97b20f 100644 --- a/src-tauri/src/database.rs +++ b/src-tauri/src/database.rs @@ -2,18 +2,31 @@ use std::{ fs::File, io::{Error, Read}, path::Path, + str::FromStr, }; use crate::get_basepath; +use serde::{Deserialize, Serialize}; use sqlx::{migrate::MigrateDatabase, Sqlite, SqlitePool}; use tauri::{ipc::RuntimeCapability, App, AssetResolver, Manager, Url}; + +struct DBFileEntry { + id: u64, + relative_file_path: String, + file_name: String, +} + +#[derive(Debug, Serialize, Deserialize)] +pub enum DBError { + DatabaseLocationError(String), + DatabaseConnectionError(String), + DatabaseQueryError(String), +} async fn populate_file_db(db: &SqlitePool) {} -fn get_database_path(app_handle: &tauri::AppHandle) -> Result { +fn get_database_path(app_handle: &tauri::AppHandle) -> Result { if let Some(basepath) = get_basepath(app_handle.clone()) { - let db_path = Path::new("Documents") - .join(Path::new("Knowledgebase")) - .join("db.sqlite"); + let db_path = Path::new(&basepath).join("db.sqlite"); let resolved_db_path = match app_handle .path() @@ -21,52 +34,44 @@ fn get_database_path(app_handle: &tauri::AppHandle) -> Result { { Ok(resolved_knowledgebase_path) => resolved_knowledgebase_path, - Err(_) => return Err(()), + Err(e) => return Err(DBError::DatabaseLocationError(e.to_string())), }; - let unicode_db_path = &resolved_db_path.to_string_lossy().to_owned(); + let unicode_db_path = resolved_db_path.to_string_lossy().as_ref().to_string(); + return Ok(unicode_db_path); } - Err(()) + Err(DBError::DatabaseLocationError( + "No knowledgebase defined".to_string(), + )) } #[tauri::command] -pub async fn initialize_database(app_handle: tauri::AppHandle) { - if let Some(basepath) = get_basepath(app_handle.clone()) { - let db_path = Path::new("Documents") - .join(Path::new("Knowledgebase")) - .join("db.sqlite"); - - let resolved_db_path = match app_handle - .path() - .resolve(db_path, tauri::path::BaseDirectory::Home) - { - Ok(resolved_knowledgebase_path) => resolved_knowledgebase_path, - - Err(_) => return, - }; - let unicode_db_path = &resolved_db_path.to_string_lossy().to_owned(); - if !Sqlite::database_exists(&unicode_db_path) - .await - .unwrap_or(false) - { - match Sqlite::create_database(&unicode_db_path).await { - Ok(_) => println!("Create db success"), - Err(error) => panic!("error: {}", error), - } +pub async fn initialize_database(app_handle: tauri::AppHandle) -> Result<(), DBError> { + let unicode_db_path = get_database_path(&app_handle)?; + if !Sqlite::database_exists(&unicode_db_path) + .await + .unwrap_or(false) + { + match Sqlite::create_database(&unicode_db_path).await { + Ok(_) => println!("Create db success"), + Err(error) => panic!("error: {}", error), } - let db = SqlitePool::connect(unicode_db_path).await.unwrap(); - let result = sqlx::query( - "CREATE TABLE IF NOT EXISTS files + } + let db = SqlitePool::connect(&unicode_db_path) + .await + .map_err(|e| DBError::DatabaseConnectionError(e.to_string()))?; + let _ = sqlx::query( + "CREATE TABLE IF NOT EXISTS files ( id INTEGER PRIMARY KEY NOT NULL, relative_path TEXT NOT NULL, file_name TEXT NOT NULL );", - ) - .execute(&db) - .await - .unwrap(); + ) + .execute(&db) + .await + .map_err(|e| DBError::DatabaseQueryError(e.to_string()))?; - let result = sqlx::query( - "CREATE TABLE IF NOT EXISTS file_diffs + let _ = sqlx::query( + "CREATE TABLE IF NOT EXISTS file_diffs ( id INTEGER NOT NULL, client_id INTEGER NOT NULL, @@ -77,14 +82,79 @@ pub async fn initialize_database(app_handle: tauri::AppHandle) { PRIMARY KEY (id, client_id) ) ;", - ) - .execute(&db) - .await - .unwrap(); - } + ) + .execute(&db) + .await + .map_err(|e| DBError::DatabaseQueryError(e.to_string()))?; + db.close().await; + Ok(()) } #[tauri::command] -async fn store_diff(file_path: String, file_name: String, diff: String) {} +async fn store_diff( + app_handle: &tauri::AppHandle, + file_path: String, + file_name: String, + diff: String, +) -> Result<(), DBError> { + Ok(()) +} -async fn add_file(file_path: String, file_name: String) {} +async fn get_file_id( + app_handle: &tauri::AppHandle, + relative_file_path: &str, + file_name: &str, +) -> Result { + let unicode_db_path = get_database_path(&app_handle)?; + let db = SqlitePool::connect(&unicode_db_path) + .await + .map_err(|e| DBError::DatabaseConnectionError(e.to_string()))?; + + let (id, _, _): (i32, String, String) = sqlx::query_as(&format!( + " + SELECT * + FROM files + WHERE relative_path IS '{relative_file_path}' + AND file_name IS '{file_name}' + " + )) + .fetch_one(&db) + .await + .map_err(|e| DBError::DatabaseQueryError(e.to_string()))?; + db.close().await; + Ok(id) +} +pub async fn add_file( + app_handle: &tauri::AppHandle, + relative_file_path: &str, + file_name: &str, +) -> Result<(), DBError> { + if get_file_id(app_handle, relative_file_path, file_name) + .await + .is_ok() + { + return Ok(()); + } else { + println!( + "{:?}", + get_file_id(app_handle, relative_file_path, file_name).await + ); + } + let unicode_db_path = get_database_path(&app_handle)?; + let db = SqlitePool::connect(&unicode_db_path) + .await + .map_err(|e| DBError::DatabaseConnectionError(e.to_string()))?; + + let _ = sqlx::query(&format!( + " + INSERT INTO + files (relative_path, file_name) + VALUES + ('{relative_file_path}', '{file_name}');" + )) + .execute(&db) + .await + .map_err(|e| DBError::DatabaseQueryError(e.to_string()))?; + db.close().await; + Ok(()) +} diff --git a/src-tauri/src/file_tree.rs b/src-tauri/src/file_tree.rs index bb8388a..4ea9c09 100644 --- a/src-tauri/src/file_tree.rs +++ b/src-tauri/src/file_tree.rs @@ -1,4 +1,5 @@ -use crate::get_basepath; +use crate::{database::add_file, get_basepath}; +use futures::future::{BoxFuture, FutureExt}; use html_tag::HtmlTag; use shellexpand; use std::{ @@ -6,14 +7,20 @@ use std::{ path::Path, }; #[tauri::command] -pub fn dir_tree_html(app_handle: tauri::AppHandle, filter: Vec) -> String { - if let Some(basepath) = get_basepath(app_handle) { - add_dir_tree_node(&Path::new(&basepath), &filter).to_html() +pub async fn dir_tree_html(app_handle: tauri::AppHandle, filter: Vec) -> String { + if let Some(basepath) = get_basepath(app_handle.clone()) { + add_dir_tree_node(&app_handle, &Path::new(&basepath), &filter) + .await + .to_html() } else { String::new() } } -fn add_dir_tree_node(path: &Path, filter: &Vec) -> HtmlTag { +async fn add_dir_tree_node( + app_handle: &tauri::AppHandle, + path: &Path, + filter: &Vec, +) -> HtmlTag { let mut html = HtmlTag::new("div") .with_class("filetree-node") .with_id(&format!( @@ -46,10 +53,17 @@ fn add_dir_tree_node(path: &Path, filter: &Vec) -> HtmlTag { if let Ok(dir_entry) = dir_entry_res { if let Ok(metadata) = fs::metadata(dir_entry.path()) { if metadata.is_file() { + add_file( + app_handle, + path.to_string_lossy().as_ref(), + dir_entry.file_name().to_string_lossy().as_ref(), + ) + .await; html.add_child(div_from_dir_entry(&dir_entry)) } else if metadata.is_dir() { html.add_child( - add_dir_tree_node(&dir_entry.path(), &filter) + Box::pin(add_dir_tree_node(app_handle, &dir_entry.path(), &filter)) + .await .with_attribute("style", "visibility: hidden; height: 0px;"), // .with_style("visibility", "hidden") // .with_style("height", "0px"), );