Skip to main content

yog_book/
state.rs

1//! Per-book navigation state.
2
3use crate::Book;
4
5#[derive(Debug, Clone, Default)]
6pub struct BookViewState {
7    pub cat:   usize,
8    pub entry: usize,
9    pub page:  usize,
10}
11
12impl BookViewState {
13    /// Handle a navigation event string (cat:N, entry:N, prev_page, next_page).
14    /// Returns true if state changed.
15    pub fn handle(&mut self, ev: &str, book: &Book) -> bool {
16        if let Some(n) = ev.strip_prefix("cat:") {
17            if let Ok(i) = n.parse::<usize>() {
18                if i < book.categories.len() && i != self.cat {
19                    self.cat   = i;
20                    self.entry = 0;
21                    self.page  = 0;
22                    return true;
23                }
24            }
25        } else if let Some(n) = ev.strip_prefix("entry:") {
26            if let Ok(i) = n.parse::<usize>() {
27                let entries = self.entries_in_cat(book);
28                if i < entries.len() && i != self.entry {
29                    self.entry = i;
30                    self.page  = 0;
31                    return true;
32                }
33            }
34        } else if ev == "prev_page" {
35            if self.page > 0 {
36                self.page -= 1;
37                return true;
38            }
39        } else if ev == "next_page" {
40            let max = self.page_count(book);
41            if self.page + 1 < max {
42                self.page += 1;
43                return true;
44            }
45        }
46        false
47    }
48
49    pub fn entries_in_cat<'b>(&self, book: &'b Book) -> Vec<&'b crate::BookEntry> {
50        let cat_id = book.categories.get(self.cat).map(|c| c.id.as_str()).unwrap_or("");
51        book.entries.iter().filter(|e| e.category == cat_id).collect()
52    }
53
54    pub fn current_entry<'b>(&self, book: &'b Book) -> Option<&'b crate::BookEntry> {
55        self.entries_in_cat(book).into_iter().nth(self.entry)
56    }
57
58    pub fn page_count(&self, book: &Book) -> usize {
59        self.current_entry(book).map(|e| e.pages.len().max(1)).unwrap_or(1)
60    }
61}