diff --git a/src-tauri/src/commands/history_commands.rs b/src-tauri/src/commands/history_commands.rs index 35843b3e..24c8de31 100644 --- a/src-tauri/src/commands/history_commands.rs +++ b/src-tauri/src/commands/history_commands.rs @@ -136,6 +136,11 @@ pub fn clear_clipboard_history_older_than(duration_type: String, older_then: Str // Convert older_then string to an integer. let duration_value: i64 = older_then.parse().unwrap_or(0); + println!( + "Clearing clipboard history older than {} {}", + duration_value, duration_type + ); + match duration_type.as_str() { "days" => { if duration_value == 0 { @@ -164,6 +169,40 @@ pub fn clear_clipboard_history_older_than(duration_type: String, older_then: Str "ok".to_string() } +#[tauri::command] +pub fn clear_recent_clipboard_history(duration_type: String, duration: String) -> String { + let duration_value: i64 = duration.parse().unwrap_or(0); + + println!( + "Clearing recent clipboard history for last {} {}", + duration_value, duration_type + ); + + match duration_type.as_str() { + "hour" => { + history_service::delete_recent_clipboard_history(Duration::hours(duration_value)); + } + "days" => { + history_service::delete_recent_clipboard_history(Duration::days(duration_value)); + } + "weeks" => { + history_service::delete_recent_clipboard_history(Duration::weeks(duration_value)); + } + "months" => { + history_service::delete_recent_clipboard_history(Duration::days(30 * duration_value)); + } + "year" => { + history_service::delete_recent_clipboard_history(Duration::days(356 * duration_value)); + } + _ => { + println!("Unsupported duration type: {}", duration_type); + return "error".to_string(); + } + } + + "ok".to_string() +} + #[tauri::command(async)] pub async fn save_to_file_history_item( history_id: String, diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs index 5c00028e..8e8b7938 100644 --- a/src-tauri/src/main.rs +++ b/src-tauri/src/main.rs @@ -913,6 +913,7 @@ async fn main() { history_commands::get_recent_clipboard_histories, history_commands::get_clipboard_histories_within_date_range, history_commands::clear_clipboard_history_older_than, + history_commands::clear_recent_clipboard_history, history_commands::count_clipboard_histories, history_commands::insert_clipboard_history, history_commands::update_clipboard_history_by_id, diff --git a/src-tauri/src/services/history_service.rs b/src-tauri/src/services/history_service.rs index cba5158b..210911d8 100644 --- a/src-tauri/src/services/history_service.rs +++ b/src-tauri/src/services/history_service.rs @@ -1,6 +1,4 @@ use crate::clipboard::LanguageDetectOptions; -use diesel::dsl::max; -use diesel::sql_types::Bool; use lazy_static::lazy_static; use crate::db::establish_pool_db_connection; @@ -16,7 +14,7 @@ use regex::Regex; use serde_json::to_string; use base64::{engine::general_purpose, Engine as _}; -use chrono::{Duration, NaiveDateTime}; +use chrono::{Duration, NaiveDateTime, Utc}; use std::{collections::HashMap, sync::Mutex}; use diesel::prelude::*; @@ -47,6 +45,9 @@ use crate::services::utils::{ use super::utils::is_valid_json; +use diesel::debug_query; +use diesel::sqlite::Sqlite; + type ImageHashSize = [u8; 8]; lazy_static! { @@ -237,7 +238,7 @@ pub fn add_clipboard_history_from_image( if !is_favorite_item && should_auto_star_on_double_copy { match first_item { Ok(first_item) => { - let current_time = chrono::Utc::now().timestamp_millis(); + let current_time = Utc::now().timestamp_millis(); let time_difference = current_time - first_item.updated_at; if first_item.history_id == existing_history.history_id @@ -257,8 +258,8 @@ pub fn add_clipboard_history_from_image( let _ = diesel::update(clipboard_history.filter(history_id.eq(&existing_history.history_id))) .set(( is_favorite.eq(is_favorite_item), - updated_at.eq(chrono::Utc::now().timestamp_millis()), - updated_date.eq(chrono::Utc::now().naive_utc()), + updated_at.eq(Utc::now().timestamp_millis()), + updated_date.eq(Utc::now().naive_utc()), )) .execute(connection); } else { @@ -350,10 +351,10 @@ fn create_new_history( links: None, detected_language: None, pinned_order_number: None, - created_at: chrono::Utc::now().timestamp_millis(), - updated_at: chrono::Utc::now().timestamp_millis(), - created_date: chrono::Utc::now().naive_utc(), - updated_date: chrono::Utc::now().naive_utc(), + created_at: Utc::now().timestamp_millis(), + updated_at: Utc::now().timestamp_millis(), + created_date: Utc::now().naive_utc(), + updated_date: Utc::now().naive_utc(), } } @@ -417,7 +418,7 @@ pub fn add_clipboard_history_from_text( if !is_favorite_item && should_auto_star_on_double_copy { match first_item { Ok(first_item) => { - let current_time = chrono::Utc::now().timestamp_millis(); + let current_time = Utc::now().timestamp_millis(); let time_difference = current_time - first_item.updated_at; if first_item.history_id == existing_history.history_id @@ -440,8 +441,8 @@ pub fn add_clipboard_history_from_text( let _ = diesel::update(clipboard_history.filter(history_id.eq(&existing_history.history_id))) .set(( is_favorite.eq(is_favorite_item), - updated_at.eq(chrono::Utc::now().timestamp_millis()), - updated_date.eq(chrono::Utc::now().naive_utc()), + updated_at.eq(Utc::now().timestamp_millis()), + updated_date.eq(Utc::now().naive_utc()), )) .execute(connection); @@ -528,10 +529,10 @@ pub fn add_clipboard_history_from_text( links: Some(found_links_json).filter(|_| _is_link), detected_language: detected_language_str, pinned_order_number: None, - created_at: chrono::Utc::now().timestamp_millis(), - updated_at: chrono::Utc::now().timestamp_millis(), - created_date: chrono::Utc::now().naive_utc(), - updated_date: chrono::Utc::now().naive_utc(), + created_at: Utc::now().timestamp_millis(), + updated_at: Utc::now().timestamp_millis(), + created_date: Utc::now().naive_utc(), + updated_date: Utc::now().naive_utc(), }; let _ = insert_clipboard_history(&new_history); @@ -595,41 +596,98 @@ pub fn get_clipboard_history_by_id(history_id_value: &String) -> Option String { +pub fn delete_clipboard_history_older_than(age: Duration) -> Result { let connection = &mut establish_pool_db_connection(); - let threshold_date = (chrono::Utc::now() - age).naive_utc(); + let now = Utc::now().timestamp_millis(); + let threshold_timestamp = now - age.num_milliseconds(); - let image_items_to_delete = clipboard_history - .filter(created_date.lt(threshold_date).and(is_image.eq(true))) - .load::(connection) - .expect("Error loading clipboard history items"); + // Handle image files + let image_items_to_delete = clipboard_history::table + .filter(updated_at.lt(threshold_timestamp).and(is_image.eq(true))) + .load::(connection)?; for item in image_items_to_delete.iter() { if let Some(ref path) = item.image_path_full_res { - match delete_file_and_maybe_parent(&Path::new(path)) { - Ok(_) => println!("Successfully deleted image file: {}", path), - Err(e) => eprintln!("Error deleting image file {}: {}", path, e), + if let Err(e) = delete_file_and_maybe_parent(&Path::new(path)) { + eprintln!("Error deleting image file {}: {}", path, e); } } } - let links_items_to_delete = clipboard_history - .filter(created_date.lt(threshold_date).and(is_link.eq(true))) - .load::(connection) - .expect("Error loading clipboard history items"); + // Handle link items + let links_items_to_delete = clipboard_history::table + .filter(updated_at.lt(threshold_timestamp).and(is_link.eq(true))) + .load::(connection)?; let history_ids_to_delete: Vec = links_items_to_delete .iter() .map(|item| item.history_id.clone()) .collect(); - let _ = - diesel::delete(clipboard_history.filter(created_date.lt(threshold_date))).execute(connection); + // Perform the main delete operation + let deleted_count = + diesel::delete(clipboard_history::table.filter(updated_at.lt(threshold_timestamp))) + .execute(connection)?; + // Delete associated link metadata delete_link_metadata_by_history_ids(&history_ids_to_delete); - "ok".to_string() + Ok(format!("Successfully deleted {} items", deleted_count)) +} + +pub fn delete_recent_clipboard_history( + delete_duration: Duration, +) -> Result { + let connection = &mut establish_pool_db_connection(); + + let now = Utc::now().timestamp_millis(); + let delete_threshold = now - delete_duration.num_milliseconds(); + + // Find records to delete (newer than delete_threshold) + let records_to_delete = clipboard_history::table + .filter(updated_at.gt(delete_threshold)) + .load::(connection)?; + + // Handle image files + let image_items: Vec<&ClipboardHistory> = records_to_delete + .iter() + .filter(|item| item.is_image == Some(true)) + .collect(); + + for item in image_items { + if let Some(ref path) = item.image_path_full_res { + if let Err(e) = delete_file_and_maybe_parent(&Path::new(path)) { + eprintln!("Error deleting image file {}: {}", path, e); + } + } + } + + println!("deleted_count: {:?}", records_to_delete); + + // Handle link items + let link_items: Vec<&ClipboardHistory> = records_to_delete + .iter() + .filter(|item| item.is_link == Some(true)) + .collect(); + + let history_ids_to_delete: Vec = link_items + .iter() + .map(|item| item.history_id.clone()) + .collect(); + + // Perform the main delete operation + let deleted_count = + diesel::delete(clipboard_history::table.filter(updated_at.gt(delete_threshold))) + .execute(connection)?; + + // Delete associated link metadata + delete_link_metadata_by_history_ids(&history_ids_to_delete); + + Ok(format!( + "Successfully deleted {} recent items", + deleted_count + )) } pub fn delete_all_clipboard_histories() -> String {