diff --git a/src/ui/pagination.rs b/src/ui/pagination.rs index 03576e0..12eb000 100644 --- a/src/ui/pagination.rs +++ b/src/ui/pagination.rs @@ -2,6 +2,69 @@ use std::sync::{Arc, RwLock}; use crate::traits::ListItem; +pub struct ApiPage { + pub offset: u32, + pub total: u32, + pub items: Vec, +} +pub type FetchPageFn = dyn Fn(u32) -> Option> + Send + Sync; +pub struct ApiResult { + offset: Arc>, + limit: u32, + pub total: u32, + pub items: Arc>>, + fetch_page: Arc>, +} + +impl ApiResult { + pub fn new(limit: u32, fetch_page: Arc>) -> ApiResult { + let items = Arc::new(RwLock::new(Vec::new())); + if let Some(first_page) = fetch_page(0) { + items.write().unwrap().extend(first_page.items); + ApiResult { + offset: Arc::new(RwLock::new(first_page.offset)), + limit, + total: first_page.total, + items, + fetch_page: fetch_page.clone(), + } + } else { + ApiResult { + offset: Arc::new(RwLock::new(0)), + limit, + total: 0, + items, + fetch_page: fetch_page.clone(), + } + } + } + + fn offset(&self) -> u32 { + *self.offset.read().unwrap() + } + + pub fn at_end(&self) -> bool { + (self.offset() + self.limit as u32) >= self.total + } + + pub fn next(&self) -> Option> { + let offset = self.offset() + self.limit as u32; + debug!("fetching next page at offset {}", offset); + if !self.at_end() { + if let Some(next_page) = (self.fetch_page)(offset) { + *self.offset.write().unwrap() = next_page.offset; + self.items.write().unwrap().extend(next_page.items.clone()); + Some(next_page.items) + } else { + None + } + } else { + debug!("paginator is at end"); + None + } + } +} + pub type Paginator = Box>>) + Send + Sync>; pub struct Pagination { @@ -36,7 +99,7 @@ impl Pagination { *self.max_content.write().unwrap() = None; *self.callback.write().unwrap() = None; } - pub fn set(&mut self, max_content: usize, callback: Paginator) { + pub fn set(&self, max_content: usize, callback: Paginator) { *self.max_content.write().unwrap() = Some(max_content); *self.callback.write().unwrap() = Some(callback); }