mirror of
https://github.com/0PandaDEV/Qopy.git
synced 2025-04-22 05:34:04 +02:00
206 lines
5.9 KiB
Rust
206 lines
5.9 KiB
Rust
use crate::utils::types::{ContentType, HistoryItem};
|
|
use base64::{engine::general_purpose::STANDARD, Engine};
|
|
use rand::distributions::Alphanumeric;
|
|
use rand::{thread_rng, Rng};
|
|
use sqlx::{Row, SqlitePool};
|
|
use std::fs;
|
|
use tauri_plugin_aptabase::EventTracker;
|
|
|
|
pub async fn initialize_history(pool: &SqlitePool) -> Result<(), Box<dyn std::error::Error>> {
|
|
let id: String = thread_rng()
|
|
.sample_iter(&Alphanumeric)
|
|
.take(16)
|
|
.map(char::from)
|
|
.collect();
|
|
|
|
sqlx::query(
|
|
"INSERT INTO history (id, source, content_type, content, timestamp) VALUES (?, ?, ?, ?, CURRENT_TIMESTAMP)"
|
|
)
|
|
.bind(id)
|
|
.bind("System")
|
|
.bind("text")
|
|
.bind("Welcome to your clipboard history!")
|
|
.execute(pool)
|
|
.await?;
|
|
|
|
Ok(())
|
|
}
|
|
|
|
#[tauri::command]
|
|
pub async fn get_history(pool: tauri::State<'_, SqlitePool>) -> Result<Vec<HistoryItem>, String> {
|
|
let rows = sqlx::query(
|
|
"SELECT id, source, source_icon, content_type, content, favicon, timestamp, language FROM history ORDER BY timestamp DESC",
|
|
)
|
|
.fetch_all(&*pool)
|
|
.await
|
|
.map_err(|e| e.to_string())?;
|
|
|
|
let items = rows
|
|
.iter()
|
|
.map(|row| HistoryItem {
|
|
id: row.get("id"),
|
|
source: row.get("source"),
|
|
source_icon: row.get("source_icon"),
|
|
content_type: ContentType::from(row.get::<String, _>("content_type")),
|
|
content: row.get("content"),
|
|
favicon: row.get("favicon"),
|
|
timestamp: row.get("timestamp"),
|
|
language: row.get("language"),
|
|
})
|
|
.collect();
|
|
|
|
Ok(items)
|
|
}
|
|
|
|
#[tauri::command]
|
|
pub async fn add_history_item(
|
|
app_handle: tauri::AppHandle,
|
|
pool: tauri::State<'_, SqlitePool>,
|
|
item: HistoryItem,
|
|
) -> Result<(), String> {
|
|
let (id, source, source_icon, content_type, content, favicon, timestamp, language) =
|
|
item.to_row();
|
|
|
|
let existing = sqlx::query("SELECT id FROM history WHERE content = ? AND content_type = ?")
|
|
.bind(&content)
|
|
.bind(&content_type)
|
|
.fetch_optional(&*pool)
|
|
.await
|
|
.map_err(|e| e.to_string())?;
|
|
|
|
match existing {
|
|
Some(_) => {
|
|
sqlx::query(
|
|
"UPDATE history SET timestamp = strftime('%Y-%m-%dT%H:%M:%f+00:00', 'now') WHERE content = ? AND content_type = ?"
|
|
)
|
|
.bind(&content)
|
|
.bind(&content_type)
|
|
.execute(&*pool)
|
|
.await
|
|
.map_err(|e| e.to_string())?;
|
|
}
|
|
None => {
|
|
sqlx::query(
|
|
"INSERT INTO history (id, source, source_icon, content_type, content, favicon, timestamp, language) VALUES (?, ?, ?, ?, ?, ?, ?, ?)"
|
|
)
|
|
.bind(id)
|
|
.bind(source)
|
|
.bind(source_icon)
|
|
.bind(content_type)
|
|
.bind(content)
|
|
.bind(favicon)
|
|
.bind(timestamp)
|
|
.bind(language)
|
|
.execute(&*pool)
|
|
.await
|
|
.map_err(|e| e.to_string())?;
|
|
}
|
|
}
|
|
|
|
let _ = app_handle.track_event("history_item_added", Some(serde_json::json!({
|
|
"content_type": item.content_type.to_string()
|
|
})));
|
|
|
|
Ok(())
|
|
}
|
|
|
|
#[tauri::command]
|
|
pub async fn search_history(
|
|
pool: tauri::State<'_, SqlitePool>,
|
|
query: String,
|
|
) -> Result<Vec<HistoryItem>, String> {
|
|
let query = format!("%{}%", query);
|
|
let rows = sqlx::query(
|
|
"SELECT id, source, source_icon, content_type, content, favicon, timestamp, language FROM history WHERE content LIKE ? ORDER BY timestamp DESC"
|
|
)
|
|
.bind(query)
|
|
.fetch_all(&*pool)
|
|
.await
|
|
.map_err(|e| e.to_string())?;
|
|
|
|
let items = rows
|
|
.iter()
|
|
.map(|row| HistoryItem {
|
|
id: row.get("id"),
|
|
source: row.get("source"),
|
|
source_icon: row.get("source_icon"),
|
|
content_type: ContentType::from(row.get::<String, _>("content_type")),
|
|
content: row.get("content"),
|
|
favicon: row.get("favicon"),
|
|
timestamp: row.get("timestamp"),
|
|
language: row.get("language"),
|
|
})
|
|
.collect();
|
|
|
|
Ok(items)
|
|
}
|
|
|
|
#[tauri::command]
|
|
pub async fn load_history_chunk(
|
|
pool: tauri::State<'_, SqlitePool>,
|
|
offset: i64,
|
|
limit: i64,
|
|
) -> Result<Vec<HistoryItem>, String> {
|
|
let rows = sqlx::query(
|
|
"SELECT id, source, source_icon, content_type, content, favicon, timestamp, language FROM history ORDER BY timestamp DESC LIMIT ? OFFSET ?"
|
|
)
|
|
.bind(limit)
|
|
.bind(offset)
|
|
.fetch_all(&*pool)
|
|
.await
|
|
.map_err(|e| e.to_string())?;
|
|
|
|
let items = rows
|
|
.iter()
|
|
.map(|row| HistoryItem {
|
|
id: row.get("id"),
|
|
source: row.get("source"),
|
|
source_icon: row.get("source_icon"),
|
|
content_type: ContentType::from(row.get::<String, _>("content_type")),
|
|
content: row.get("content"),
|
|
favicon: row.get("favicon"),
|
|
timestamp: row.get("timestamp"),
|
|
language: row.get("language"),
|
|
})
|
|
.collect();
|
|
|
|
Ok(items)
|
|
}
|
|
|
|
#[tauri::command]
|
|
pub async fn delete_history_item(
|
|
app_handle: tauri::AppHandle,
|
|
pool: tauri::State<'_, SqlitePool>,
|
|
id: String,
|
|
) -> Result<(), String> {
|
|
sqlx::query("DELETE FROM history WHERE id = ?")
|
|
.bind(id)
|
|
.execute(&*pool)
|
|
.await
|
|
.map_err(|e| e.to_string())?;
|
|
|
|
let _ = app_handle.track_event("history_item_deleted", None);
|
|
|
|
Ok(())
|
|
}
|
|
|
|
#[tauri::command]
|
|
pub async fn clear_history(
|
|
app_handle: tauri::AppHandle,
|
|
pool: tauri::State<'_, SqlitePool>
|
|
) -> Result<(), String> {
|
|
sqlx::query("DELETE FROM history")
|
|
.execute(&*pool)
|
|
.await
|
|
.map_err(|e| e.to_string())?;
|
|
|
|
let _ = app_handle.track_event("history_cleared", None);
|
|
|
|
Ok(())
|
|
}
|
|
|
|
#[tauri::command]
|
|
pub async fn read_image(filename: String) -> Result<String, String> {
|
|
let bytes = fs::read(filename).map_err(|e| e.to_string())?;
|
|
Ok(STANDARD.encode(bytes))
|
|
}
|