2025-09-11 18:36:42 -04:00
|
|
|
use std::sync::{Arc, OnceLock};
|
2025-09-11 13:42:18 -04:00
|
|
|
use dioxus::prelude::*;
|
|
|
|
|
mod frontend;
|
|
|
|
|
mod file_handling;
|
|
|
|
|
mod document_extraction;
|
2025-09-11 14:00:33 -04:00
|
|
|
mod indexing;
|
2025-09-11 14:08:46 -04:00
|
|
|
mod config;
|
2025-09-11 23:15:50 -04:00
|
|
|
mod search;
|
2024-06-10 12:45:33 -04:00
|
|
|
|
2025-09-11 18:36:42 -04:00
|
|
|
// Global indexing service for signal handling
|
|
|
|
|
static INDEXING_SERVICE: OnceLock<Arc<indexing::IndexingService>> = OnceLock::new();
|
|
|
|
|
|
2024-06-10 12:45:33 -04:00
|
|
|
fn main() {
|
2025-09-11 18:36:42 -04:00
|
|
|
// Initialize global indexing service
|
|
|
|
|
let indexing_service = Arc::new(indexing::IndexingService::new());
|
|
|
|
|
INDEXING_SERVICE.set(indexing_service.clone()).expect("Failed to set global indexing service");
|
|
|
|
|
|
|
|
|
|
// Set up Ctrl-C signal handler
|
|
|
|
|
ctrlc::set_handler(|| {
|
|
|
|
|
eprintln!("Received Ctrl-C, shutting down gracefully...");
|
|
|
|
|
if let Some(service) = INDEXING_SERVICE.get() {
|
|
|
|
|
if let Err(e) = service.graceful_shutdown() {
|
|
|
|
|
eprintln!("Error during graceful shutdown: {}", e);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
std::process::exit(0);
|
|
|
|
|
}).expect("Error setting Ctrl-C handler");
|
|
|
|
|
|
2025-09-12 00:31:52 -04:00
|
|
|
LaunchBuilder::desktop()
|
|
|
|
|
.with_cfg(
|
|
|
|
|
dioxus_desktop::Config::new()
|
|
|
|
|
.with_custom_head(format!("<style>{}</style>", include_str!("../assets/styles.css")))
|
|
|
|
|
.with_window(dioxus_desktop::WindowBuilder::new()
|
|
|
|
|
.with_title("QuickSearch - File Indexer & Search")
|
|
|
|
|
.with_resizable(true)
|
|
|
|
|
.with_inner_size(dioxus_desktop::LogicalSize::new(1000.0, 700.0))
|
|
|
|
|
)
|
|
|
|
|
)
|
|
|
|
|
.launch(app);
|
2025-09-11 14:00:33 -04:00
|
|
|
}
|
|
|
|
|
|
2025-09-12 00:31:52 -04:00
|
|
|
|
2025-09-11 14:00:33 -04:00
|
|
|
fn app() -> Element {
|
2025-09-11 14:08:46 -04:00
|
|
|
let config = match config::Config::load() {
|
|
|
|
|
Ok(config) => config,
|
|
|
|
|
Err(e) => {
|
|
|
|
|
eprintln!("Failed to load config: {}", e);
|
|
|
|
|
return rsx! { div { "Failed to load configuration" } };
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
2025-09-11 18:36:42 -04:00
|
|
|
let indexing_service = INDEXING_SERVICE.get().expect("Indexing service not initialized").clone();
|
2025-09-11 14:00:33 -04:00
|
|
|
|
|
|
|
|
rsx! {
|
|
|
|
|
frontend::App {
|
2025-09-11 14:08:46 -04:00
|
|
|
indexing_service: indexing_service,
|
|
|
|
|
config: config
|
2025-09-11 14:00:33 -04:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2024-06-10 13:56:01 -04:00
|
|
|
|
2024-06-10 18:16:28 -04:00
|
|
|
/*
|
2025-09-11 23:15:50 -04:00
|
|
|
Duplicate files:
|
|
|
|
|
SELECT name, count(*) as cnt, path FROM files GROUP BY hash HAVING cnt > 1 ORDER BY cnt DESC;
|
2025-09-11 13:42:18 -04:00
|
|
|
|
2025-09-11 23:15:50 -04:00
|
|
|
Full text search:
|
2026-04-21 02:34:40 -04:00
|
|
|
SELECT d.name, d.path, d.text, snippet(st, 1 , "<b>", "</b>", "<b>...</b>", 64) as "snip" FROM searchabletext AS st JOIN documents d ON d.id = st.rowid WHERE st.text MATCH 'searchstring'
|
2025-09-11 23:15:50 -04:00
|
|
|
|
|
|
|
|
Filename search:
|
|
|
|
|
SELECT name, path FROM files WHERE name LIKE '%searchstring%';
|
2025-09-11 14:00:33 -04:00
|
|
|
*/
|