1use 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 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}