From 1110a2614b141ac23a68a68a9a04900fade640f7 Mon Sep 17 00:00:00 2001 From: Peter Cai Date: Fri, 10 Apr 2020 20:57:53 +0800 Subject: [PATCH] render: implement pagination --- src/lib.rs | 2 +- src/render.rs | 47 ++++++++++++++++++++++++++++++++++++++---- src/utils.rs | 4 +++- theme/default/home.hbs | 8 +++++-- 4 files changed, 53 insertions(+), 8 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index f38ad82..6a43946 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -120,7 +120,7 @@ async fn default_route(_req: Request, url: Url) -> MyResult { // Home page (this cannot be registered as a standalone route due to our Router) if path == "/" { return Response::new_with_opt_str_and_init( - Some(&render::render_homepage().await?), + Some(&render::render_homepage(url).await?), ResponseInit::new() .status(200) .headers(headers!{ diff --git a/src/render.rs b/src/render.rs index ab20390..0021413 100644 --- a/src/render.rs +++ b/src/render.rs @@ -55,7 +55,9 @@ struct HomePagePost { #[derive(Serialize)] struct HomePageContext { blog: &'static BlogRootContext, - posts: Vec + posts: Vec, + prev: Option, + next: Option } lazy_static! { @@ -98,14 +100,51 @@ fn build_handlebars() -> Handlebars<'static> { return hbs; } -pub async fn render_homepage() -> MyResult { +pub async fn render_homepage(url: Url) -> MyResult { + let params = UrlSearchParams::new_with_str(&url.search()) + .map_err(|_| Error::BadRequest("Failed to parse query string".into()))?; let hbs = build_handlebars(); let mut context = HomePageContext { blog: &ROOT_CONTEXT, - posts: vec![] + posts: vec![], + prev: None, + next: None }; let posts_list = blog::PostsList::load().await; - for uuid in posts_list.0.iter() { + + // Pagination + let mut posts_len = posts_list.0.len(); + let mut offset: isize = 0; + if let Some(offset_str) = params.get("offset") { + offset = offset_str.parse().internal_err()?; + if offset > posts_len as isize || offset < 0 { + return Err(Error::BadRequest("invalid offset".into())); + } + posts_len = posts_len - offset as usize; + } + + if offset > 0 { + let new_offset = + std::cmp::max(offset - crate::CONFIG.posts_per_page as isize, 0) as usize; + if new_offset != 0 { + context.prev = Some(format!("/?offset={}", new_offset)); + } else { + context.prev = Some("/".into()); + } + } + + if posts_len == 0 { + return Err(Error::BadRequest("offset too large".into())); + } + + if posts_len > crate::CONFIG.posts_per_page { + context.next = Some( + format!("/?offset={}", + offset + crate::CONFIG.posts_per_page as isize)); + } + + // List posts + for uuid in posts_list.0.iter().skip(offset as usize).take(crate::CONFIG.posts_per_page) { let post = blog::Post::find_by_uuid(uuid).await?; let post_cache = blog::PostContentCache::find_or_render(&post).await; context.posts.push(HomePagePost { diff --git a/src/utils.rs b/src/utils.rs index 44c5705..a2d22c5 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -153,7 +153,9 @@ pub struct Config { // Description of the blog pub description: String, // Plugin identifier used for Standard Notes - pub plugin_identifier: String + pub plugin_identifier: String, + // How many posts to show in one page + pub posts_per_page: usize } #[derive(BuildDateTime)] diff --git a/theme/default/home.hbs b/theme/default/home.hbs index 17fa6ae..c9a5345 100644 --- a/theme/default/home.hbs +++ b/theme/default/home.hbs @@ -19,8 +19,12 @@ {{ /each }}