diff options
| author | metamuffin <metamuffin@disroot.org> | 2026-02-26 03:02:24 +0100 |
|---|---|---|
| committer | metamuffin <metamuffin@disroot.org> | 2026-02-26 03:02:24 +0100 |
| commit | eb6648770e7de66ccafe44d114ecbb2c1eaf444d (patch) | |
| tree | 2bce9f579b3ea7313f84df94b27fad813c66e9e1 /server/src/ui/items.rs | |
| parent | 7f7deec27e69ed110c52caddaa3a0c04430e71d9 (diff) | |
| download | jellything-eb6648770e7de66ccafe44d114ecbb2c1eaf444d.tar jellything-eb6648770e7de66ccafe44d114ecbb2c1eaf444d.tar.bz2 jellything-eb6648770e7de66ccafe44d114ecbb2c1eaf444d.tar.zst | |
implement application-side continuation tokens
Diffstat (limited to 'server/src/ui/items.rs')
| -rw-r--r-- | server/src/ui/items.rs | 69 |
1 files changed, 47 insertions, 22 deletions
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 <metamuffin.org> */ -use super::error::MyError; -use rocket::{Either, get, response::content::RawHtml, serde::json::Json}; -#[get("/items?<page>&<filter..>")] -pub fn r_items( - ri: RequestInfo, - page: Option<usize>, - filter: ANodeFilterSort, -) -> Result<Either<RawHtml<String>, Json<ApiItemsResponse>>, 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?<cont>")] +pub fn r_items(ri: RequestInfo, cont: Option<&str>) -> MyResult<UiResponse> { + 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::<Result<Vec<_>, _>>()?; + + 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)) } |