aboutsummaryrefslogtreecommitdiff
path: root/server/src/ui
diff options
context:
space:
mode:
authormetamuffin <metamuffin@disroot.org>2026-02-27 20:56:20 +0100
committermetamuffin <metamuffin@disroot.org>2026-02-27 20:56:20 +0100
commit7930d543a2aa68d4ad2958605827d7eb1baa91f8 (patch)
treefe59d1f549e303a96b78d3e925d75abb70b73af0 /server/src/ui
parentc05bfcc2775f0e11db6e856bfcf06d0419c35d54 (diff)
downloadjellything-7930d543a2aa68d4ad2958605827d7eb1baa91f8.tar
jellything-7930d543a2aa68d4ad2958605827d7eb1baa91f8.tar.bz2
jellything-7930d543a2aa68d4ad2958605827d7eb1baa91f8.tar.zst
reimplement Object as slice type
Diffstat (limited to 'server/src/ui')
-rw-r--r--server/src/ui/account/mod.rs6
-rw-r--r--server/src/ui/account/settings.rs6
-rw-r--r--server/src/ui/admin/users.rs4
-rw-r--r--server/src/ui/home.rs70
-rw-r--r--server/src/ui/items.rs7
-rw-r--r--server/src/ui/node.rs295
-rw-r--r--server/src/ui/player.rs15
7 files changed, 207 insertions, 196 deletions
diff --git a/server/src/ui/account/mod.rs b/server/src/ui/account/mod.rs
index b106fc7..9e5fa39 100644
--- a/server/src/ui/account/mod.rs
+++ b/server/src/ui/account/mod.rs
@@ -82,10 +82,10 @@ pub fn r_account_login_post(
})?;
if let Some(ur) = user_row {
let mut user = txn.get(ur)?.unwrap();
- user = user.as_object().remove(USER_PASSWORD_REQUIRE_CHANGE);
- user = user.as_object().insert(USER_PASSWORD, &password_hash);
+ user = user.remove(USER_PASSWORD_REQUIRE_CHANGE);
+ user = user.insert(USER_PASSWORD, &password_hash);
if let Some(name) = &form.display_name {
- user = user.as_object().insert(USER_NAME, &name);
+ user = user.insert(USER_NAME, &name);
}
txn.update(ur, user)?;
}
diff --git a/server/src/ui/account/settings.rs b/server/src/ui/account/settings.rs
index 9a98c09..2585061 100644
--- a/server/src/ui/account/settings.rs
+++ b/server/src/ui/account/settings.rs
@@ -7,7 +7,7 @@ use super::format_form_error;
use crate::{auth::hash_password, request_info::RequestInfo, ui::error::MyResult};
use anyhow::anyhow;
use jellycommon::{
- jellyobject::{Object, ObjectBuffer, Path, Tag},
+ jellyobject::{Object, Path, Tag},
routes::u_account_settings,
*,
};
@@ -104,7 +104,7 @@ pub fn r_account_settings_post(
Ok(Flash::success(Redirect::to(u_account_settings()), out))
}
-fn update_user(ri: &RequestInfo, update: impl Fn(Object) -> ObjectBuffer) -> MyResult<()> {
+fn update_user(ri: &RequestInfo, update: impl Fn(&Object) -> Box<Object>) -> MyResult<()> {
let login = ri
.require_user()?
.get(USER_LOGIN)
@@ -118,7 +118,7 @@ fn update_user(ri: &RequestInfo, update: impl Fn(Object) -> ObjectBuffer) -> MyR
.ok_or(anyhow!("user vanished"))?;
let user = txn.get(user_row)?.unwrap();
- let new_user = update(user.as_object());
+ let new_user = update(&user);
txn.update(user_row, new_user)?;
Ok(())
diff --git a/server/src/ui/admin/users.rs b/server/src/ui/admin/users.rs
index 85f241b..4b11279 100644
--- a/server/src/ui/admin/users.rs
+++ b/server/src/ui/admin/users.rs
@@ -46,7 +46,7 @@ pub fn r_admin_users(ri: RequestInfo) -> MyResult<RawHtml<String>> {
Ok(ri.respond_ui(&AdminUserList {
ri: &ri.render_info(),
- users: &users.iter().map(|u| u.as_object()).collect::<Vec<_>>(),
+ users: &users.iter().map(|u| &**u).collect::<Vec<_>>(),
}))
}
@@ -97,7 +97,7 @@ pub fn r_admin_user(ri: RequestInfo<'_>, name: &str) -> MyResult<RawHtml<String>
Ok(ri.respond_ui(&AdminUser {
ri: &ri.render_info(),
- user: user.as_object(),
+ user: &user,
}))
}
diff --git a/server/src/ui/home.rs b/server/src/ui/home.rs
index 6cb6a77..17cac83 100644
--- a/server/src/ui/home.rs
+++ b/server/src/ui/home.rs
@@ -7,11 +7,11 @@
use super::error::MyResult;
use crate::request_info::RequestInfo;
use anyhow::{Context, Result};
-use jellycommon::jellyobject::{Object, ObjectBuffer};
-use jellydb::Query;
-use jellyui::components::home::HomeRow;
+use jellycommon::{Nku, jellyobject::EMPTY};
+use jellydb::{Query, helper::DatabaseReturnExt};
+use jellyui::components::home::{Home, HomeRow};
use rocket::{get, response::content::RawHtml};
-use std::str::FromStr;
+use std::{borrow::Cow, str::FromStr};
#[get("/home")]
pub fn r_home(ri: RequestInfo<'_>) -> MyResult<RawHtml<String>> {
@@ -28,7 +28,7 @@ pub fn r_home(ri: RequestInfo<'_>) -> MyResult<RawHtml<String>> {
"home.bin.latest_music",
"FILTER (visi = visi AND kind = musi) SORT DESCENDING BY FIRST rldt",
)?);
- rows.push(home_row_highlight(
+ rows.extend(home_row_highlight(
&ri,
"home.bin.daily_random",
"FILTER (visi = visi AND kind = movi) SORT RANDOM",
@@ -38,51 +38,59 @@ pub fn r_home(ri: RequestInfo<'_>) -> MyResult<RawHtml<String>> {
"home.bin.max_rating",
"SORT DESCENDING BY FIRST rtng.imdb",
)?);
- rows.push(home_row_highlight(
+ rows.extend(home_row_highlight(
&ri,
"home.bin.daily_random",
"FILTER (visi = visi AND kind = show) SORT RANDOM",
)?);
- Ok(ri.respond_ui(rows))
+ Ok(ri.respond_ui(&Home {
+ ri: &ri.render_info(),
+ rows: &rows,
+ }))
}
-fn home_row(ri: &RequestInfo<'_>, title: &str, query: &str) -> Result<HomeRow> {
+fn home_row(
+ ri: &RequestInfo<'_>,
+ title: &'static str,
+ query: &str,
+) -> Result<(&'static str, HomeRow<'static>)> {
let q = Query::from_str(query).context("parse query")?;
- let mut res = ObjectBuffer::empty();
- ri.state.database.transaction(&mut |txn| {
+ ri.state.database.transaction_ret(|txn| {
let rows = txn.query(q.clone())?.take(16).collect::<Result<Vec<_>>>()?;
let mut nkus = Vec::new();
for (row, _) in rows {
let node = txn.get(row)?.unwrap();
- nkus.push(ObjectBuffer::new(&mut [(NKU_NODE.0, &node.as_object())]));
+ nkus.push(Nku {
+ node: Cow::Owned(node),
+ role: None,
+ userdata: Cow::Borrowed(EMPTY),
+ });
}
- let nkus = nkus.iter().map(|n| n.as_object()).collect::<Vec<_>>(); // TODO -_-
-
- res = Object::EMPTY.insert(NODELIST_DISPLAYSTYLE, NLSTYLE_INLINE);
- res = res.as_object().insert(NODELIST_TITLE, title);
- res = res.as_object().insert_multi(NODELIST_ITEM, &nkus);
-
- Ok(())
- })?;
- Ok(res)
+ Ok((title, HomeRow::Inline(nkus)))
+ })
}
-fn home_row_highlight(ri: &RequestInfo<'_>, title: &str, query: &str) -> Result<HomeRow> {
+fn home_row_highlight(
+ ri: &RequestInfo<'_>,
+ title: &'static str,
+ query: &str,
+) -> Result<Option<(&'static str, HomeRow<'static>)>> {
let q = Query::from_str(query).context("parse query")?;
- let mut res = ObjectBuffer::empty();
- ri.state.database.transaction(&mut |txn| {
+ ri.state.database.transaction_ret(|txn| {
let Some(row) = txn.query(q.clone())?.next() else {
- return Ok(());
+ return Ok(None);
};
let row = row?.0;
let node = txn.get(row)?.unwrap();
- let nku = ObjectBuffer::new(&mut [(NKU_NODE.0, &node.as_object())]);
- res = Object::EMPTY.insert(NODELIST_DISPLAYSTYLE, NLSTYLE_HIGHLIGHT);
- res = res.as_object().insert(NODELIST_TITLE, title);
- res = res.as_object().insert(NODELIST_ITEM, nku.as_object());
- Ok(())
- })?;
- Ok(res)
+ Ok(Some((
+ title,
+ HomeRow::Highlight(Nku {
+ node: Cow::Owned(node),
+ role: None,
+ userdata: Cow::Borrowed(EMPTY),
+ }),
+ )))
+ })
}
diff --git a/server/src/ui/items.rs b/server/src/ui/items.rs
index b800914..6071bcc 100644
--- a/server/src/ui/items.rs
+++ b/server/src/ui/items.rs
@@ -8,12 +8,13 @@ use crate::{request_info::RequestInfo, ui::error::MyResult};
use anyhow::anyhow;
use base64::{Engine, prelude::BASE64_URL_SAFE};
use jellycommon::{
- jellyobject::{Object, Path},
+ jellyobject::{EMPTY, Path},
*,
};
use jellydb::{Filter, Query};
use jellyui::components::items::Items;
use rocket::{get, response::content::RawHtml};
+use std::borrow::Cow;
#[get("/items?<cont>")]
pub fn r_items(ri: RequestInfo, cont: Option<&str>) -> MyResult<RawHtml<String>> {
@@ -49,8 +50,8 @@ pub fn r_items(ri: RequestInfo, cont: Option<&str>) -> MyResult<RawHtml<String>>
items: &items
.iter()
.map(|node| Nku {
- node: node.as_object(),
- userdata: Object::EMPTY,
+ node: Cow::Borrowed(&node),
+ userdata: Cow::Borrowed(EMPTY),
role: None,
})
.collect::<Vec<_>>(),
diff --git a/server/src/ui/node.rs b/server/src/ui/node.rs
index 55a1d09..ca07bac 100644
--- a/server/src/ui/node.rs
+++ b/server/src/ui/node.rs
@@ -5,186 +5,183 @@
*/
use super::error::MyResult;
-use crate::{request_info::RequestInfo, ui_responder::UiResponse};
-use anyhow::Result;
+use crate::request_info::RequestInfo;
+use anyhow::anyhow;
use jellycommon::{
- jellyobject::{OBB, Object, ObjectBuffer, ObjectBufferBuilder, Path},
+ jellyobject::{EMPTY, Path},
*,
};
-use jellydb::{Filter, MultiBehaviour, Query, Sort, SortOrder, Transaction, ValueSort};
-use rocket::get;
-use std::collections::BTreeMap;
+use jellydb::{Filter, Query};
+use jellyui::components::node_page::NodePage;
+use rocket::{get, response::content::RawHtml};
+use std::borrow::Cow;
#[get("/n/<slug>")]
-pub fn r_node(ri: RequestInfo<'_>, slug: &str) -> MyResult<UiResponse> {
+pub fn r_node(ri: RequestInfo<'_>, slug: &str) -> MyResult<RawHtml<String>> {
ri.require_user()?;
- let mut page = OBB::new();
+ let mut nku = None;
ri.state.database.transaction(&mut |txn| {
if let Some(row) = txn.query_single(Query {
filter: Filter::Match(Path(vec![NO_SLUG.0]), slug.into()),
..Default::default()
})? {
let n = txn.get(row)?.unwrap();
- let nku = Object::EMPTY.insert(NKU_NODE, n.as_object());
- let nku = nku.as_object();
-
- page = OBB::new();
- let title = nku
- .get(NKU_NODE)
- .unwrap_or_default()
- .get(NO_TITLE)
- .unwrap_or_default();
-
- page.push(VIEW_TITLE, title);
- page.push(VIEW_NODE_PAGE, nku);
- c_children(&mut page, txn, row, &nku)?;
- c_credits(&mut page, txn, &nku)?;
- c_credited(&mut page, txn, row)?;
+ nku = Some(Nku {
+ node: Cow::Owned(n),
+ userdata: Cow::Borrowed(EMPTY),
+ role: None,
+ });
}
Ok(())
})?;
+ let Some(nku) = nku else {
+ Err(anyhow!("no such node"))?
+ };
- Ok(ri.respond_ui(page))
+ Ok(ri.respond_ui(&NodePage {
+ ri: &ri.render_info(),
+ nku,
+ }))
}
-fn c_children(
- page: &mut ObjectBufferBuilder,
- txn: &mut dyn Transaction,
- row: u64,
- nku: &Object,
-) -> Result<()> {
- let kind = nku
- .get(NKU_NODE)
- .unwrap_or_default()
- .get(NO_KIND)
- .unwrap_or(KIND_COLLECTION);
+// fn c_children(
+// page: &mut ObjectBufferBuilder,
+// txn: &mut dyn Transaction,
+// row: u64,
+// nku: &Object,
+// ) -> Result<()> {
+// let kind = nku
+// .get(NKU_NODE)
+// .unwrap_or_default()
+// .get(NO_KIND)
+// .unwrap_or(KIND_COLLECTION);
- let (order, path) = match kind {
- KIND_CHANNEL => (SortOrder::Descending, Path(vec![NO_RELEASEDATE.0])),
- KIND_SEASON | KIND_SHOW => (SortOrder::Ascending, Path(vec![NO_INDEX.0])),
- _ => (SortOrder::Ascending, Path(vec![NO_TITLE.0])),
- };
+// let (order, path) = match kind {
+// KIND_CHANNEL => (SortOrder::Descending, Path(vec![NO_RELEASEDATE.0])),
+// KIND_SEASON | KIND_SHOW => (SortOrder::Ascending, Path(vec![NO_INDEX.0])),
+// _ => (SortOrder::Ascending, Path(vec![NO_TITLE.0])),
+// };
- let children_rows = txn
- .query(Query {
- sort: Sort::Value(ValueSort {
- multi: MultiBehaviour::First,
- offset: None,
- order,
- path,
- }),
- filter: Filter::All(vec![
- Filter::Match(Path(vec![NO_VISIBILITY.0]), VISI_VISIBLE.into()),
- Filter::Match(Path(vec![NO_PARENT.0]), row.into()),
- ]),
- ..Default::default()
- })?
- .collect::<Result<Vec<_>>>()?;
+// let children_rows = txn
+// .query(Query {
+// sort: Sort::Value(ValueSort {
+// multi: MultiBehaviour::First,
+// offset: None,
+// order,
+// path,
+// }),
+// filter: Filter::All(vec![
+// Filter::Match(Path(vec![NO_VISIBILITY.0]), VISI_VISIBLE.into()),
+// Filter::Match(Path(vec![NO_PARENT.0]), row.into()),
+// ]),
+// ..Default::default()
+// })?
+// .collect::<Result<Vec<_>>>()?;
- if children_rows.is_empty() {
- return Ok(());
- }
+// if children_rows.is_empty() {
+// return Ok(());
+// }
- let mut list = ObjectBufferBuilder::default();
+// let mut list = ObjectBufferBuilder::default();
- list.push(
- NODELIST_DISPLAYSTYLE,
- match kind {
- KIND_SEASON | KIND_SHOW => NLSTYLE_LIST,
- _ => NLSTYLE_GRID,
- },
- );
+// list.push(
+// NODELIST_DISPLAYSTYLE,
+// match kind {
+// KIND_SEASON | KIND_SHOW => NLSTYLE_LIST,
+// _ => NLSTYLE_GRID,
+// },
+// );
- for (row, _) in children_rows {
- list.push(
- NODELIST_ITEM,
- Object::EMPTY
- .insert(NKU_NODE, txn.get(row)?.unwrap().as_object())
- .as_object(),
- );
- }
+// for (row, _) in children_rows {
+// list.push(
+// NODELIST_ITEM,
+// Object::EMPTY
+// .insert(NKU_NODE, txn.get(row)?.unwrap().as_object())
+// .as_object(),
+// );
+// }
- page.push(VIEW_NODE_LIST, list.finish().as_object());
- Ok(())
-}
+// page.push(VIEW_NODE_LIST, list.finish().as_object());
+// Ok(())
+// }
-fn c_credits(
- page: &mut ObjectBufferBuilder,
- txn: &mut dyn Transaction,
- nku: &Object,
-) -> Result<()> {
- if !nku.get(NKU_NODE).unwrap_or_default().has(NO_CREDIT.0) {
- return Ok(());
- }
+// fn c_credits(
+// page: &mut ObjectBufferBuilder,
+// txn: &mut dyn Transaction,
+// nku: &Object,
+// ) -> Result<()> {
+// if !nku.get(NKU_NODE).unwrap_or_default().has(NO_CREDIT.0) {
+// return Ok(());
+// }
- let mut cats = BTreeMap::<_, Vec<_>>::new();
- for cred in nku.get(NKU_NODE).unwrap_or_default().iter(NO_CREDIT) {
- let mut o = ObjectBuffer::empty();
- if let Some(row) = cred.get(CR_NODE) {
- let node = txn.get(row)?.unwrap();
- o = o.as_object().insert(NKU_NODE, node.as_object());
- }
- if let Some(role) = cred.get(CR_ROLE) {
- o = o.as_object().insert(NKU_ROLE, role)
- }
- cats.entry(cred.get(CR_KIND).unwrap_or(CRCAT_CREW))
- .or_default()
- .push(o);
- }
- let mut cats = cats.into_iter().collect::<Vec<_>>();
- cats.sort_by_key(|(c, _)| match *c {
- CRCAT_CAST => 0,
- CRCAT_CREW => 1,
- _ => 100,
- });
- for (cat, elems) in cats {
- let mut list = ObjectBufferBuilder::default();
- list.push(NODELIST_DISPLAYSTYLE, NLSTYLE_INLINE);
- list.push(NODELIST_TITLE, &format!("tag.cred.kind.{cat}"));
- for item in elems {
- list.push(NODELIST_ITEM, item.as_object());
- }
- page.push(VIEW_NODE_LIST, list.finish().as_object());
- }
+// let mut cats = BTreeMap::<_, Vec<_>>::new();
+// for cred in nku.get(NKU_NODE).unwrap_or_default().iter(NO_CREDIT) {
+// let mut o = ObjectBuffer::empty();
+// if let Some(row) = cred.get(CR_NODE) {
+// let node = txn.get(row)?.unwrap();
+// o = o.as_object().insert(NKU_NODE, node.as_object());
+// }
+// if let Some(role) = cred.get(CR_ROLE) {
+// o = o.as_object().insert(NKU_ROLE, role)
+// }
+// cats.entry(cred.get(CR_KIND).unwrap_or(CRCAT_CREW))
+// .or_default()
+// .push(o);
+// }
+// let mut cats = cats.into_iter().collect::<Vec<_>>();
+// cats.sort_by_key(|(c, _)| match *c {
+// CRCAT_CAST => 0,
+// CRCAT_CREW => 1,
+// _ => 100,
+// });
+// for (cat, elems) in cats {
+// let mut list = ObjectBufferBuilder::default();
+// list.push(NODELIST_DISPLAYSTYLE, NLSTYLE_INLINE);
+// list.push(NODELIST_TITLE, &format!("tag.cred.kind.{cat}"));
+// for item in elems {
+// list.push(NODELIST_ITEM, item.as_object());
+// }
+// page.push(VIEW_NODE_LIST, list.finish().as_object());
+// }
- Ok(())
-}
+// Ok(())
+// }
-fn c_credited(page: &mut ObjectBufferBuilder, txn: &mut dyn Transaction, row: u64) -> Result<()> {
- let children_rows = txn
- .query(Query {
- sort: Sort::Value(ValueSort {
- multi: MultiBehaviour::First,
- offset: None,
- order: SortOrder::Ascending,
- path: Path(vec![NO_TITLE.0]),
- }),
- filter: Filter::All(vec![
- Filter::Match(Path(vec![NO_VISIBILITY.0]), VISI_VISIBLE.into()),
- Filter::Match(Path(vec![NO_CREDIT.0, CR_NODE.0]), row.into()),
- ]),
- ..Default::default()
- })?
- .collect::<Result<Vec<_>>>()?;
+// fn c_credited(page: &mut ObjectBufferBuilder, txn: &mut dyn Transaction, row: u64) -> Result<()> {
+// let children_rows = txn
+// .query(Query {
+// sort: Sort::Value(ValueSort {
+// multi: MultiBehaviour::First,
+// offset: None,
+// order: SortOrder::Ascending,
+// path: Path(vec![NO_TITLE.0]),
+// }),
+// filter: Filter::All(vec![
+// Filter::Match(Path(vec![NO_VISIBILITY.0]), VISI_VISIBLE.into()),
+// Filter::Match(Path(vec![NO_CREDIT.0, CR_NODE.0]), row.into()),
+// ]),
+// ..Default::default()
+// })?
+// .collect::<Result<Vec<_>>>()?;
- if children_rows.is_empty() {
- return Ok(());
- }
+// if children_rows.is_empty() {
+// return Ok(());
+// }
- let mut list = ObjectBufferBuilder::default();
- list.push(NODELIST_DISPLAYSTYLE, NLSTYLE_GRID);
- list.push(NODELIST_TITLE, "node.credited");
+// let mut list = ObjectBufferBuilder::default();
+// list.push(NODELIST_DISPLAYSTYLE, NLSTYLE_GRID);
+// list.push(NODELIST_TITLE, "node.credited");
- for (row, _) in children_rows {
- list.push(
- NODELIST_ITEM,
- Object::EMPTY
- .insert(NKU_NODE, txn.get(row)?.unwrap().as_object())
- .as_object(),
- );
- }
+// for (row, _) in children_rows {
+// list.push(
+// NODELIST_ITEM,
+// Object::EMPTY
+// .insert(NKU_NODE, txn.get(row)?.unwrap().as_object())
+// .as_object(),
+// );
+// }
- page.push(VIEW_NODE_LIST, list.finish().as_object());
- Ok(())
-}
+// page.push(VIEW_NODE_LIST, list.finish().as_object());
+// Ok(())
+// }
diff --git a/server/src/ui/player.rs b/server/src/ui/player.rs
index 1050abb..c6c177e 100644
--- a/server/src/ui/player.rs
+++ b/server/src/ui/player.rs
@@ -5,13 +5,15 @@
*/
use super::error::MyResult;
use crate::request_info::RequestInfo;
+use anyhow::anyhow;
use jellycommon::{
- jellyobject::{Object, ObjectBuffer, Path},
+ jellyobject::{EMPTY, Path},
*,
};
use jellydb::{Filter, Query};
use jellyui::components::node_page::Player;
use rocket::{get, response::content::RawHtml};
+use std::borrow::Cow;
// fn jellynative_url(action: &str, seek: f64, secret: &str, node: &str, session: &str) -> String {
// let protocol = if CONF.tls { "https" } else { "http" };
@@ -31,22 +33,25 @@ pub fn r_player(ri: RequestInfo<'_>, t: Option<f64>, slug: &str) -> MyResult<Raw
ri.require_user()?;
let _ = t;
- let mut node = ObjectBuffer::empty();
+ let mut node = None;
ri.state.database.transaction(&mut |txn| {
if let Some(row) = txn.query_single(Query {
filter: Filter::Match(Path(vec![NO_SLUG.0]), slug.into()),
..Default::default()
})? {
- node = txn.get(row)?.unwrap();
+ node = Some(txn.get(row)?.unwrap());
}
Ok(())
})?;
+ let Some(node) = node else {
+ Err(anyhow!("no such node"))?
+ };
Ok(ri.respond_ui(&Player {
ri: &ri.render_info(),
nku: Nku {
- node: node.as_object(),
- userdata: Object::EMPTY,
+ node: Cow::Borrowed(&node),
+ userdata: Cow::Borrowed(EMPTY),
role: None,
},
}))