aboutsummaryrefslogtreecommitdiff
path: root/server
diff options
context:
space:
mode:
Diffstat (limited to 'server')
-rw-r--r--server/src/routes/mod.rs3
-rw-r--r--server/src/routes/progress.rs28
-rw-r--r--server/src/routes/ui/home.rs23
3 files changed, 53 insertions, 1 deletions
diff --git a/server/src/routes/mod.rs b/server/src/routes/mod.rs
index 48fdf96..9211a1e 100644
--- a/server/src/routes/mod.rs
+++ b/server/src/routes/mod.rs
@@ -8,6 +8,7 @@ use api::{r_api_account_login, r_api_node_raw, r_api_root, r_api_version};
use base64::Engine;
use jellybase::CONF;
use log::warn;
+use progress::r_player_progress;
use rand::random;
use rocket::{
catchers, config::SecretKey, fairing::AdHoc, fs::FileServer, get, http::Header, routes, Build,
@@ -37,6 +38,7 @@ use ui::{
};
pub mod api;
+pub mod progress;
pub mod stream;
pub mod ui;
@@ -92,6 +94,7 @@ pub fn build_rocket(database: Database, federation: Federation) -> Rocket<Build>
r_assets_js_map,
r_stream,
r_player,
+ r_player_progress,
r_account_login,
r_account_login_post,
r_account_register,
diff --git a/server/src/routes/progress.rs b/server/src/routes/progress.rs
new file mode 100644
index 0000000..170ed97
--- /dev/null
+++ b/server/src/routes/progress.rs
@@ -0,0 +1,28 @@
+use std::collections::HashMap;
+
+use super::ui::{account::session::Session, error::MyResult};
+use jellybase::database::Database;
+use rocket::{post, State};
+
+#[post("/n/<id>/progress?<t>")]
+pub async fn r_player_progress(
+ session: Session,
+ db: &State<Database>,
+ id: &str,
+ t: Option<f64>,
+) -> MyResult<()> {
+ db.user_progess.fetch_and_update(&session.user.name, |p| {
+ let mut m = p.unwrap_or_else(|| HashMap::new());
+ if let Some(t) = t {
+ m.insert(id.to_string(), t);
+ } else {
+ m.remove(&id.to_string());
+ }
+ if m.is_empty() {
+ None
+ } else {
+ Some(m)
+ }
+ })?;
+ Ok(())
+}
diff --git a/server/src/routes/ui/home.rs b/server/src/routes/ui/home.rs
index 4ba3fc3..3f1f0d0 100644
--- a/server/src/routes/ui/home.rs
+++ b/server/src/routes/ui/home.rs
@@ -59,6 +59,22 @@ pub fn r_home(sess: Session, db: &State<Database>) -> MyResult<DynLayoutPage> {
.map(|k| k.to_owned())
.collect::<Vec<_>>();
+ let continue_watching = db
+ .user_progess
+ .get(&sess.user.name)?
+ .unwrap_or_default()
+ .into_iter()
+ .map(|(n, p)| {
+ Ok((
+ n.clone(),
+ db.node.get(&n)?.context("child does not exist")?.public,
+ p,
+ ))
+ })
+ .collect::<anyhow::Result<Vec<_>>>()?
+ .into_iter()
+ .collect::<Vec<_>>();
+
Ok(LayoutPage {
title: "Home".to_string(),
content: markup::new! {
@@ -67,6 +83,12 @@ pub fn r_home(sess: Session, db: &State<Database>) -> MyResult<DynLayoutPage> {
.homelist { ul {@for (id, node) in &toplevel {
li { @NodeCard { id, node } }
}}}
+ @if !continue_watching.is_empty() {
+ h2 { "Continue Watching" }
+ .homelist { ul {@for (id, node, _p) in &continue_watching {
+ li { @NodeCard { id, node } }
+ }}}
+ }
h2 { "Latest Releases" }
.homelist { ul {@for (id, node) in &latest {
li { @NodeCard { id, node } }
@@ -75,7 +97,6 @@ pub fn r_home(sess: Session, db: &State<Database>) -> MyResult<DynLayoutPage> {
.homelist { ul {@for (id, node) in &random {
li { @NodeCard { id, node } }
}}}
- p.error { "TODO: continue watching" }
p.error { "TODO: recently added" }
p.error { "TODO: best rating" }
},