Skip to main content

verso/store/
highlights.rs

1use rusqlite::{params, Connection};
2
3#[derive(Debug, Clone, Copy, PartialEq, Eq)]
4pub enum AnchorStatus {
5    Ok,
6    Drifted,
7    Lost,
8}
9
10impl AnchorStatus {
11    pub fn as_str(self) -> &'static str {
12        match self {
13            Self::Ok => "ok",
14            Self::Drifted => "drifted",
15            Self::Lost => "lost",
16        }
17    }
18    pub fn parse(s: &str) -> Self {
19        match s {
20            "drifted" => Self::Drifted,
21            "lost" => Self::Lost,
22            _ => Self::Ok,
23        }
24    }
25}
26
27#[derive(Debug, Clone)]
28pub struct Highlight {
29    pub id: i64,
30    pub book_id: i64,
31    pub spine_idx: u32,
32    pub chapter_title: Option<String>,
33    pub char_offset_start: u64,
34    pub char_offset_end: u64,
35    pub text: String,
36    pub context_before: Option<String>,
37    pub context_after: Option<String>,
38    pub note: Option<String>,
39    pub anchor_status: AnchorStatus,
40}
41
42pub fn insert(c: &mut Connection, h: &Highlight) -> anyhow::Result<i64> {
43    c.execute(
44        "INSERT INTO highlights(book_id, spine_idx, chapter_title, char_offset_start, char_offset_end,
45                                text, context_before, context_after, note, anchor_status)
46         VALUES (?,?,?,?,?,?,?,?,?,?)",
47        params![h.book_id, h.spine_idx, h.chapter_title, h.char_offset_start, h.char_offset_end,
48                h.text, h.context_before, h.context_after, h.note, h.anchor_status.as_str()],
49    )?;
50    Ok(c.last_insert_rowid())
51}
52
53pub fn delete(c: &mut Connection, id: i64) -> anyhow::Result<()> {
54    c.execute("DELETE FROM highlights WHERE id = ?", params![id])?;
55    Ok(())
56}
57
58pub fn list(c: &Connection, book_id: i64) -> anyhow::Result<Vec<Highlight>> {
59    let mut stmt = c.prepare(
60        "SELECT id, book_id, spine_idx, chapter_title, char_offset_start, char_offset_end,
61                text, context_before, context_after, note, anchor_status
62         FROM highlights WHERE book_id = ? ORDER BY spine_idx, char_offset_start",
63    )?;
64    let rows: Vec<Highlight> = stmt
65        .query_map(params![book_id], |r| {
66            Ok(Highlight {
67                id: r.get(0)?,
68                book_id: r.get(1)?,
69                spine_idx: r.get(2)?,
70                chapter_title: r.get(3)?,
71                char_offset_start: r.get(4)?,
72                char_offset_end: r.get(5)?,
73                text: r.get(6)?,
74                context_before: r.get(7)?,
75                context_after: r.get(8)?,
76                note: r.get(9)?,
77                anchor_status: AnchorStatus::parse(&r.get::<_, String>(10)?),
78            })
79        })?
80        .collect::<Result<_, _>>()?;
81    Ok(rows)
82}