From eb6648770e7de66ccafe44d114ecbb2c1eaf444d Mon Sep 17 00:00:00 2001 From: metamuffin Date: Thu, 26 Feb 2026 03:02:24 +0100 Subject: implement application-side continuation tokens --- server/src/ui/items.rs | 69 ++++++++++++++++++++++++++++++++++---------------- 1 file changed, 47 insertions(+), 22 deletions(-) (limited to 'server/src/ui/items.rs') diff --git a/server/src/ui/items.rs b/server/src/ui/items.rs index cc8c18f..6383830 100644 --- a/server/src/ui/items.rs +++ b/server/src/ui/items.rs @@ -3,27 +3,52 @@ which is licensed under the GNU Affero General Public License (version 3); see /COPYING. Copyright (C) 2026 metamuffin */ -use super::error::MyError; -use rocket::{Either, get, response::content::RawHtml, serde::json::Json}; -#[get("/items?&")] -pub fn r_items( - ri: RequestInfo, - page: Option, - filter: ANodeFilterSort, -) -> Result, Json>, MyError> { - let r = all_items(&ri.session, page, filter.clone().into())?; - Ok(if matches!(ri.accept, Accept::Json) { - Either::Right(Json(r)) - } else { - Either::Left(RawHtml(render_page( - &ItemsPage { - lang: &ri.lang, - r, - filter: &filter.clone().into(), - page: page.unwrap_or(0), - }, - ri.render_info(), - ))) - }) +use crate::{request_info::RequestInfo, ui::error::MyResult, ui_responder::UiResponse}; +use anyhow::anyhow; +use base64::{Engine, prelude::BASE64_URL_SAFE}; +use jellycommon::{ + jellyobject::{OBB, Path}, + *, +}; +use jellydb::{Filter, Query}; +use rocket::get; + +#[get("/items?")] +pub fn r_items(ri: RequestInfo, cont: Option<&str>) -> MyResult { + let cont = cont + .map(|s| BASE64_URL_SAFE.decode(s)) + .transpose() + .map_err(|_| anyhow!("invalid contination token"))?; + + let mut page = OBB::new(); + ri.state.database.transaction(&mut |txn| { + let rows = txn + .query(Query { + filter: Filter::Has(Path(vec![NO_SLUG.0])), + continuation: cont.clone(), + ..Default::default() + })? + .take(64) + .collect::, _>>()?; + + let mut list = OBB::new() + .with(NODELIST_DISPLAYSTYLE, NLSTYLE_GRID) + .with(NODELIST_TITLE, "items"); + + let mut iterstate = Vec::new(); + for (r, is) in rows { + let node = txn.get(r)?.unwrap(); + let nku = OBB::new().with(NKU_NODE, node.as_object()).finish(); + list.push(NODELIST_ITEM, nku.as_object()); + iterstate = is; + } + list.push(NODELIST_CONTINUATION, &BASE64_URL_SAFE.encode(iterstate)); + + page = OBB::new(); + page.push(VIEW_NODE_LIST, list.finish().as_object()); + + Ok(()) + })?; + Ok(ri.respond_ui(page)) } -- cgit v1.3