Skip to content

Commit 2652f26

Browse files
committed
fix: same item inserted multiple times
1 parent e559705 commit 2652f26

File tree

1 file changed

+51
-30
lines changed

1 file changed

+51
-30
lines changed

src-tauri/src/db/history.rs

+51-30
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
1-
use sqlx::{Row, SqlitePool};
1+
use crate::utils::types::{ContentType, HistoryItem};
2+
use base64::{engine::general_purpose::STANDARD, Engine};
23
use rand::distributions::Alphanumeric;
34
use rand::{thread_rng, Rng};
4-
use crate::utils::types::{HistoryItem, ContentType};
5+
use sqlx::{Row, SqlitePool};
56
use std::fs;
6-
use base64::{Engine, engine::general_purpose::STANDARD};
77

88
pub async fn initialize_history(pool: &SqlitePool) -> Result<(), Box<dyn std::error::Error>> {
99
let id: String = thread_rng()
@@ -27,19 +27,22 @@ pub async fn initialize_history(pool: &SqlitePool) -> Result<(), Box<dyn std::er
2727
#[tauri::command]
2828
pub async fn get_history(pool: tauri::State<'_, SqlitePool>) -> Result<Vec<HistoryItem>, String> {
2929
let rows = sqlx::query(
30-
"SELECT id, content_type, content, favicon, timestamp FROM history ORDER BY timestamp DESC"
30+
"SELECT id, content_type, content, favicon, timestamp FROM history ORDER BY timestamp DESC",
3131
)
3232
.fetch_all(&*pool)
3333
.await
3434
.map_err(|e| e.to_string())?;
3535

36-
let items = rows.iter().map(|row| HistoryItem {
37-
id: row.get("id"),
38-
content_type: ContentType::from(row.get::<String, _>("content_type")),
39-
content: row.get("content"),
40-
favicon: row.get("favicon"),
41-
timestamp: row.get("timestamp"),
42-
}).collect();
36+
let items = rows
37+
.iter()
38+
.map(|row| HistoryItem {
39+
id: row.get("id"),
40+
content_type: ContentType::from(row.get::<String, _>("content_type")),
41+
content: row.get("content"),
42+
favicon: row.get("favicon"),
43+
timestamp: row.get("timestamp"),
44+
})
45+
.collect();
4346

4447
Ok(items)
4548
}
@@ -50,7 +53,19 @@ pub async fn add_history_item(
5053
item: HistoryItem,
5154
) -> Result<(), String> {
5255
let (id, content_type, content, favicon, timestamp) = item.to_row();
53-
56+
57+
let last_content: Option<String> = sqlx::query_scalar(
58+
"SELECT content FROM history WHERE content_type = ? ORDER BY timestamp DESC LIMIT 1",
59+
)
60+
.bind(content_type.clone())
61+
.fetch_one(&*pool)
62+
.await
63+
.unwrap_or(None);
64+
65+
if last_content.as_deref() == Some(&content) {
66+
return Ok(());
67+
}
68+
5469
sqlx::query(
5570
"INSERT INTO history (id, content_type, content, favicon, timestamp) VALUES (?, ?, ?, ?, ?)"
5671
)
@@ -69,7 +84,7 @@ pub async fn add_history_item(
6984
#[tauri::command]
7085
pub async fn search_history(
7186
pool: tauri::State<'_, SqlitePool>,
72-
query: String
87+
query: String,
7388
) -> Result<Vec<HistoryItem>, String> {
7489
let query = format!("%{}%", query);
7590
let rows = sqlx::query(
@@ -80,13 +95,16 @@ pub async fn search_history(
8095
.await
8196
.map_err(|e| e.to_string())?;
8297

83-
let items = rows.iter().map(|row| HistoryItem {
84-
id: row.get("id"),
85-
content_type: ContentType::from(row.get::<String, _>("content_type")),
86-
content: row.get("content"),
87-
favicon: row.get("favicon"),
88-
timestamp: row.get("timestamp"),
89-
}).collect();
98+
let items = rows
99+
.iter()
100+
.map(|row| HistoryItem {
101+
id: row.get("id"),
102+
content_type: ContentType::from(row.get::<String, _>("content_type")),
103+
content: row.get("content"),
104+
favicon: row.get("favicon"),
105+
timestamp: row.get("timestamp"),
106+
})
107+
.collect();
90108

91109
Ok(items)
92110
}
@@ -95,7 +113,7 @@ pub async fn search_history(
95113
pub async fn load_history_chunk(
96114
pool: tauri::State<'_, SqlitePool>,
97115
offset: i64,
98-
limit: i64
116+
limit: i64,
99117
) -> Result<Vec<HistoryItem>, String> {
100118
let rows = sqlx::query(
101119
"SELECT id, content_type, content, favicon, timestamp FROM history ORDER BY timestamp DESC LIMIT ? OFFSET ?"
@@ -106,21 +124,24 @@ pub async fn load_history_chunk(
106124
.await
107125
.map_err(|e| e.to_string())?;
108126

109-
let items = rows.iter().map(|row| HistoryItem {
110-
id: row.get("id"),
111-
content_type: ContentType::from(row.get::<String, _>("content_type")),
112-
content: row.get("content"),
113-
favicon: row.get("favicon"),
114-
timestamp: row.get("timestamp"),
115-
}).collect();
127+
let items = rows
128+
.iter()
129+
.map(|row| HistoryItem {
130+
id: row.get("id"),
131+
content_type: ContentType::from(row.get::<String, _>("content_type")),
132+
content: row.get("content"),
133+
favicon: row.get("favicon"),
134+
timestamp: row.get("timestamp"),
135+
})
136+
.collect();
116137

117138
Ok(items)
118139
}
119140

120141
#[tauri::command]
121142
pub async fn delete_history_item(
122143
pool: tauri::State<'_, SqlitePool>,
123-
id: String
144+
id: String,
124145
) -> Result<(), String> {
125146
sqlx::query("DELETE FROM history WHERE id = ?")
126147
.bind(id)
@@ -145,4 +166,4 @@ pub async fn clear_history(pool: tauri::State<'_, SqlitePool>) -> Result<(), Str
145166
pub async fn read_image(filename: String) -> Result<String, String> {
146167
let bytes = fs::read(filename).map_err(|e| e.to_string())?;
147168
Ok(STANDARD.encode(bytes))
148-
}
169+
}

0 commit comments

Comments
 (0)