Skip to main content

kimun_notes/components/note_browser/
search_provider.rs

1use std::sync::Arc;
2
3use async_trait::async_trait;
4use kimun_core::NoteVault;
5use kimun_core::nfs::{NoteEntryData, VaultPath};
6use kimun_core::note::NoteContentData;
7
8use super::{NoteBrowserProvider, format_journal_date};
9use crate::components::file_list::FileListEntry;
10
11pub struct SearchNotesProvider {
12    vault: Arc<NoteVault>,
13    last_paths: Vec<VaultPath>,
14}
15
16impl SearchNotesProvider {
17    pub fn new(vault: Arc<NoteVault>, last_paths: Vec<VaultPath>) -> Self {
18        Self { vault, last_paths }
19    }
20
21    fn to_entry(&self, entry: NoteEntryData, content: NoteContentData) -> FileListEntry {
22        let filename = entry.path.get_parent_path().1;
23        let title = if content.title.trim().is_empty() {
24            "<no title>".to_string()
25        } else {
26            content.title
27        };
28        let journal_date = self
29            .vault
30            .journal_date(&entry.path)
31            .map(format_journal_date);
32        FileListEntry::Note {
33            path: entry.path,
34            title,
35            filename,
36            journal_date,
37        }
38    }
39}
40
41#[async_trait]
42impl NoteBrowserProvider for SearchNotesProvider {
43    async fn load(&self, query: &str) -> Vec<FileListEntry> {
44        if query.is_empty() {
45            // Build a lookup map from all indexed notes so we can resolve each
46            // last_path to its full metadata in O(1).
47            let all_notes = self.vault.get_all_notes().await.unwrap_or_default();
48            let mut by_path: std::collections::HashMap<_, _> = all_notes
49                .into_iter()
50                .map(|(entry, content)| (entry.path.clone(), (entry, content)))
51                .collect();
52
53            // last_paths is most-recent-first; iterate as-is.
54            self.last_paths
55                .iter()
56                .filter_map(|path| by_path.remove(path))
57                .map(|(entry, content)| self.to_entry(entry, content))
58                .collect()
59        } else {
60            self.vault
61                .search_notes(query)
62                .await
63                .unwrap_or_default()
64                .into_iter()
65                .map(|(entry, content)| self.to_entry(entry, content))
66                .collect()
67        }
68    }
69}