aboutsummaryrefslogtreecommitdiff
path: root/server/src/ui/items.rs
diff options
context:
space:
mode:
authormetamuffin <metamuffin@disroot.org>2026-02-26 03:02:24 +0100
committermetamuffin <metamuffin@disroot.org>2026-02-26 03:02:24 +0100
commiteb6648770e7de66ccafe44d114ecbb2c1eaf444d (patch)
tree2bce9f579b3ea7313f84df94b27fad813c66e9e1 /server/src/ui/items.rs
parent7f7deec27e69ed110c52caddaa3a0c04430e71d9 (diff)
downloadjellything-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.rs69
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))
}