restructure
Some checks failed
CI - Multi-Platform Native / Build iOS (RSSuper) (push) Has been cancelled
CI - Multi-Platform Native / Build macOS (push) Has been cancelled
CI - Multi-Platform Native / Build Android (push) Has been cancelled
CI - Multi-Platform Native / Build Linux (push) Has been cancelled
CI - Multi-Platform Native / Build Summary (push) Has been cancelled
Some checks failed
CI - Multi-Platform Native / Build iOS (RSSuper) (push) Has been cancelled
CI - Multi-Platform Native / Build macOS (push) Has been cancelled
CI - Multi-Platform Native / Build Android (push) Has been cancelled
CI - Multi-Platform Native / Build Linux (push) Has been cancelled
CI - Multi-Platform Native / Build Summary (push) Has been cancelled
This commit is contained in:
171
linux/src/database/search-history-store.vala
Normal file
171
linux/src/database/search-history-store.vala
Normal file
@@ -0,0 +1,171 @@
|
||||
/*
|
||||
* SearchHistoryStore.vala
|
||||
*
|
||||
* CRUD operations for search history.
|
||||
*/
|
||||
|
||||
/**
|
||||
* SearchHistoryStore - Manages search history persistence
|
||||
*/
|
||||
public class RSSuper.SearchHistoryStore : Object {
|
||||
private Database db;
|
||||
|
||||
/**
|
||||
* Maximum number of history entries to keep
|
||||
*/
|
||||
public int max_entries { get; set; default = 100; }
|
||||
|
||||
/**
|
||||
* Signal emitted when a search is recorded
|
||||
*/
|
||||
public signal void search_recorded(SearchQuery query, int result_count);
|
||||
|
||||
/**
|
||||
* Signal emitted when history is cleared
|
||||
*/
|
||||
public signal void history_cleared();
|
||||
|
||||
/**
|
||||
* Create a new search history store
|
||||
*/
|
||||
public SearchHistoryStore(Database db) {
|
||||
this.db = db;
|
||||
}
|
||||
|
||||
/**
|
||||
* Record a search query
|
||||
*/
|
||||
public int record_search(SearchQuery query, int result_count = 0) throws Error {
|
||||
var stmt = db.prepare(
|
||||
"INSERT INTO search_history (query, filters_json, sort_option, page, page_size, result_count) " +
|
||||
"VALUES (?, ?, ?, ?, ?, ?);"
|
||||
);
|
||||
|
||||
stmt.bind_text(1, query.query, -1, null);
|
||||
stmt.bind_text(2, query.filters_json ?? "", -1, null);
|
||||
stmt.bind_text(3, SearchFilters.sort_option_to_string(query.sort), -1, null);
|
||||
stmt.bind_int(4, query.page);
|
||||
stmt.bind_int(5, query.page_size);
|
||||
stmt.bind_int(6, result_count);
|
||||
|
||||
stmt.step();
|
||||
|
||||
debug("Search recorded: %s (%d results)", query.query, result_count);
|
||||
search_recorded(query, result_count);
|
||||
|
||||
// Clean up old entries if needed
|
||||
cleanup_old_entries();
|
||||
|
||||
return 0; // Returns the last inserted row ID in SQLite
|
||||
}
|
||||
|
||||
/**
|
||||
* Get search history
|
||||
*/
|
||||
public SearchQuery[] get_history(int limit = 50) throws Error {
|
||||
var queries = new GLib.List<SearchQuery?>();
|
||||
|
||||
var stmt = db.prepare(
|
||||
"SELECT query, filters_json, sort_option, page, page_size, result_count, created_at " +
|
||||
"FROM search_history " +
|
||||
"ORDER BY created_at DESC " +
|
||||
"LIMIT ?;"
|
||||
);
|
||||
|
||||
stmt.bind_int(1, limit);
|
||||
|
||||
while (stmt.step() == Sqlite.ROW) {
|
||||
var query = row_to_query(stmt);
|
||||
queries.append(query);
|
||||
}
|
||||
|
||||
return queries_to_array(queries);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get recent searches (last 24 hours)
|
||||
*/
|
||||
public SearchQuery[] get_recent() throws Error {
|
||||
var queries = new GLib.List<SearchQuery?>();
|
||||
var now = new DateTime.now_local();
|
||||
var yesterday = now.add_days(-1);
|
||||
var threshold = yesterday.format("%Y-%m-%dT%H:%M:%S");
|
||||
|
||||
var stmt = db.prepare(
|
||||
"SELECT query, filters_json, sort_option, page, page_size, result_count, created_at " +
|
||||
"FROM search_history " +
|
||||
"WHERE created_at >= ? " +
|
||||
"ORDER BY created_at DESC " +
|
||||
"LIMIT 20;"
|
||||
);
|
||||
|
||||
stmt.bind_text(1, threshold, -1, null);
|
||||
|
||||
while (stmt.step() == Sqlite.ROW) {
|
||||
var query = row_to_query(stmt);
|
||||
queries.append(query);
|
||||
}
|
||||
|
||||
return queries_to_array(queries);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a search history entry by ID
|
||||
*/
|
||||
public void delete(int id) throws Error {
|
||||
var stmt = db.prepare("DELETE FROM search_history WHERE id = ?;");
|
||||
stmt.bind_int(1, id);
|
||||
stmt.step();
|
||||
|
||||
debug("Search history entry deleted: %d", id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear all search history
|
||||
*/
|
||||
public void clear() throws Error {
|
||||
var stmt = db.prepare("DELETE FROM search_history;");
|
||||
stmt.step();
|
||||
|
||||
debug("Search history cleared");
|
||||
history_cleared();
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear old search history entries
|
||||
*/
|
||||
private void cleanup_old_entries() throws Error {
|
||||
var stmt = db.prepare(
|
||||
"DELETE FROM search_history WHERE id NOT IN (" +
|
||||
"SELECT id FROM search_history ORDER BY created_at DESC LIMIT ?" +
|
||||
");"
|
||||
);
|
||||
|
||||
stmt.bind_int(1, max_entries);
|
||||
stmt.step();
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a database row to a SearchQuery
|
||||
*/
|
||||
private SearchQuery row_to_query(Sqlite.Statement stmt) {
|
||||
string query_str = stmt.column_text(0);
|
||||
string? filters_json = stmt.column_text(1);
|
||||
string sort_str = stmt.column_text(2);
|
||||
int page = stmt.column_int(3);
|
||||
int page_size = stmt.column_int(4);
|
||||
|
||||
return SearchQuery(query_str, page, page_size, filters_json,
|
||||
SearchFilters.sort_option_from_string(sort_str));
|
||||
}
|
||||
|
||||
private SearchQuery[] queries_to_array(GLib.List<SearchQuery?> list) {
|
||||
SearchQuery[] arr = {};
|
||||
for (unowned var node = list; node != null; node = node.next) {
|
||||
arr += node.data;
|
||||
}
|
||||
return arr;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user