diff options
| author | metamuffin <metamuffin@disroot.org> | 2023-01-18 16:16:03 +0100 | 
|---|---|---|
| committer | metamuffin <metamuffin@disroot.org> | 2023-01-18 16:16:03 +0100 | 
| commit | 46ef75431e1d34c63a690726a8ef584d175ddd30 (patch) | |
| tree | df36a2bfb9fe3e19ce9f76665b4770063a089423 /server/src/routes/ui | |
| parent | 5aa557e864bd2cf940e7164b7568e7e545817306 (diff) | |
| download | jellything-46ef75431e1d34c63a690726a8ef584d175ddd30.tar jellything-46ef75431e1d34c63a690726a8ef584d175ddd30.tar.bz2 jellything-46ef75431e1d34c63a690726a8ef584d175ddd30.tar.zst | |
restructure pages slightly
Diffstat (limited to 'server/src/routes/ui')
| -rw-r--r-- | server/src/routes/ui/error.rs | 59 | ||||
| -rw-r--r-- | server/src/routes/ui/home.rs | 14 | ||||
| -rw-r--r-- | server/src/routes/ui/layout.rs | 20 | ||||
| -rw-r--r-- | server/src/routes/ui/mod.rs | 32 | ||||
| -rw-r--r-- | server/src/routes/ui/node.rs | 61 | ||||
| -rw-r--r-- | server/src/routes/ui/style/cantarell.woff2 | bin | 0 -> 93888 bytes | |||
| -rw-r--r-- | server/src/routes/ui/style/layout.css | 45 | ||||
| -rw-r--r-- | server/src/routes/ui/style/mod.rs | 51 | 
8 files changed, 282 insertions, 0 deletions
| diff --git a/server/src/routes/ui/error.rs b/server/src/routes/ui/error.rs new file mode 100644 index 0000000..2a1f8e6 --- /dev/null +++ b/server/src/routes/ui/error.rs @@ -0,0 +1,59 @@ +use super::{layout::Layout, HtmlTemplate}; +use markup::Render; +use rocket::http::Status; +use rocket::{ +    catch, +    http::ContentType, +    response::{self, Responder}, +    Request, Response, +}; +use std::{fmt::Display, io::Cursor}; + +#[catch(default)] +pub fn r_not_found<'a>(status: Status, _request: &Request) -> HtmlTemplate<markup::DynRender<'a>> { +    HtmlTemplate( +        "Not found".to_string(), +        markup::new! { +            h2 { "Error" } +            p { @format!("{status:?}") } +        }, +    ) +} + +#[derive(Debug)] +pub struct MyError(anyhow::Error); + +impl<'r> Responder<'r, 'static> for MyError { +    fn respond_to(self, _: &'r Request<'_>) -> response::Result<'static> { +        let mut out = String::new(); +        Layout { +            title: "Error".to_string(), +            main: markup::new! { +                h2 { "An error occured. Nobody is sorry"} +                pre.error { @format!("{:?}", self.0) } +            }, +        } +        .render(&mut out) +        .unwrap(); +        Response::build() +            .header(ContentType::HTML) +            .streamed_body(Cursor::new(out)) +            .ok() +    } +} + +impl Display for MyError { +    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { +        self.0.fmt(f) +    } +} +impl From<anyhow::Error> for MyError { +    fn from(err: anyhow::Error) -> MyError { +        MyError(err) +    } +} +impl From<std::fmt::Error> for MyError { +    fn from(err: std::fmt::Error) -> MyError { +        MyError(anyhow::anyhow!("{err}")) +    } +} diff --git a/server/src/routes/ui/home.rs b/server/src/routes/ui/home.rs new file mode 100644 index 0000000..df95665 --- /dev/null +++ b/server/src/routes/ui/home.rs @@ -0,0 +1,14 @@ +use crate::routes::ui::node::NodePage; +use crate::{routes::ui::HtmlTemplate, AppState}; +use rocket::{get, State}; + +#[get("/")] +pub async fn r_home(state: &State<AppState>) -> HtmlTemplate<markup::DynRender> { +    HtmlTemplate( +        "Home".to_string(), +        markup::new! { +            p { "Welcome to Jellything" } +            @NodePage { node: state.library.root.clone() } +        }, +    ) +} diff --git a/server/src/routes/ui/layout.rs b/server/src/routes/ui/layout.rs new file mode 100644 index 0000000..1085f84 --- /dev/null +++ b/server/src/routes/ui/layout.rs @@ -0,0 +1,20 @@ +use markup::Render; + +markup::define! { +    Layout<Main: Render>(title: String, main: Main) { +        @markup::doctype() +        html { +            head { +                title { @title " - Jellything" } +                link[rel="stylesheet", href="/assets/style.css"]; +            } +            body { +                nav { +                    h1 { "Jellything" } + +                } +                #main { @main } +            } +        } +    } +} diff --git a/server/src/routes/ui/mod.rs b/server/src/routes/ui/mod.rs new file mode 100644 index 0000000..aa0259d --- /dev/null +++ b/server/src/routes/ui/mod.rs @@ -0,0 +1,32 @@ +use self::layout::Layout; +use markup::Render; +use rocket::{ +    http::ContentType, +    response::{self, Responder}, +    Request, Response, +}; +use std::io::Cursor; + +pub mod error; +pub mod home; +pub mod layout; +pub mod node; +pub mod style; + +pub struct HtmlTemplate<T>(pub String, pub T); + +impl<'r, T: Render> Responder<'r, 'static> for HtmlTemplate<T> { +    fn respond_to(self, _: &'r Request<'_>) -> response::Result<'static> { +        let mut out = String::new(); +        Layout { +            title: self.0, +            main: self.1, +        } +        .render(&mut out) +        .unwrap(); +        Response::build() +            .header(ContentType::HTML) +            .streamed_body(Cursor::new(out)) +            .ok() +    } +} diff --git a/server/src/routes/ui/node.rs b/server/src/routes/ui/node.rs new file mode 100644 index 0000000..b6d0d30 --- /dev/null +++ b/server/src/routes/ui/node.rs @@ -0,0 +1,61 @@ +use super::super::stream::rocket_uri_macro_r_stream; +use super::error::MyError; +use crate::{ +    library::{Directory, Item, Node}, +    routes::ui::HtmlTemplate, +    AppState, +}; +use anyhow::Context; +use rocket::{get, uri, State}; +use std::{ops::Deref, path::PathBuf, sync::Arc}; + +#[get("/library/<path..>")] +pub async fn r_library_node( +    path: PathBuf, +    state: &State<AppState>, +) -> Result<HtmlTemplate<markup::DynRender>, MyError> { +    let path = path.to_str().unwrap().to_string(); +    let node = state +        .library +        .nested(&path) +        .context("retrieving library node")? +        .clone(); +    Ok(HtmlTemplate( +        format!("{}", node.title()), +        markup::new! { +            @NodePage { node: node.clone() } +        }, +    )) +} + +markup::define! { +    NodePage(node: Arc<Node>) { +        @match node.deref() { +            Node::Directory(dir) => { @DirectoryPage { dir: dir.clone() } } +            Node::Item(item) => { @ItemPage { item: item.clone() } } +        } +    } +    DirectoryCard(dir: Arc<Directory>) { +        span { a[href=&uri!(r_library_node(&dir.lib_path)).to_string()] { @dir.data.name } } +    } +    DirectoryPage(dir: Arc<Directory>) { +        h1 { @dir.data.name } +        ul.directorylisting { +            @for el in &dir.children { +                li { +                    span.title { @match el.deref().to_owned() { +                        Node::Directory(dir) => { @DirectoryCard { dir } } +                        Node::Item(item) => { @ItemCard { item } } +                    }} +                } +            } +        } +    } +    ItemCard(item: Arc<Item>) { +        span { a[href=&uri!(r_library_node(&item.lib_path)).to_string()] { @item.data.title } } +    } +    ItemPage(item: Arc<Item>) { +        h1 { @item.data.title } +        video[src=&uri!(r_stream(&item.lib_path, "1,2")).to_string(), controls] {} +    } +} diff --git a/server/src/routes/ui/style/cantarell.woff2 b/server/src/routes/ui/style/cantarell.woff2Binary files differ new file mode 100644 index 0000000..76fd894 --- /dev/null +++ b/server/src/routes/ui/style/cantarell.woff2 diff --git a/server/src/routes/ui/style/layout.css b/server/src/routes/ui/style/layout.css new file mode 100644 index 0000000..0612a7e --- /dev/null +++ b/server/src/routes/ui/style/layout.css @@ -0,0 +1,45 @@ +@font-face { +    font-family: 'Cantarell'; +    src: url(/assets/cantarell.woff2) format('woff2'); +} + +* { +    color: white; +    font-family: "Cantarell", sans-serif; +    font-weight: 300; +    margin: 0px; +    padding: 0px; +} + +body { +    background-color: #1a1a1a; +    width: 100vw; +} + +nav { +    position: absolute; +    top: 0px; +    left: 0px; +    padding: 1em; +    width: calc(100vw - 2em); +    height: 2em; +    background-color: #41414144; +} + +nav h1 { +    margin: 0px; +    font-size: 1.5em; +} + +#main { +    margin-top: 5em; +    padding: 1em; +    padding-left: 3em; +    padding-right: 3em; +} + +.error { +    padding: 1em; +    color: rgb(255, 117, 117); +    font-family: monospace; +}
\ No newline at end of file diff --git a/server/src/routes/ui/style/mod.rs b/server/src/routes/ui/style/mod.rs new file mode 100644 index 0000000..f3d751b --- /dev/null +++ b/server/src/routes/ui/style/mod.rs @@ -0,0 +1,51 @@ +use rocket::{get, http::ContentType}; +use std::{ +    fs::{read_to_string, File}, +    io::Read, +    path::PathBuf, +    str::FromStr, +}; + +fn css_bundle() -> String { +    if cfg!(debug_assertions) { +        read_to_string( +            PathBuf::from_str(file!()) +                .unwrap() +                .parent() +                .unwrap() +                .join("layout.css"), +        ) +        .unwrap() +    } else { +        include_str!("layout.css").to_string() +    } +} +fn font_bundle() -> Vec<u8> { +    if cfg!(debug_assertions) { +        let mut woff = Vec::new(); + +        File::open( +            PathBuf::from_str(file!()) +                .unwrap() +                .parent() +                .unwrap() +                .join("cantarell.woff2"), +        ) +        .unwrap() +        .read_to_end(&mut woff) +        .unwrap(); +        woff +    } else { +        include_bytes!("cantarell.woff2").to_vec() +    } +} + +#[get("/assets/style.css")] +pub fn r_assets_style() -> (ContentType, String) { +    (ContentType::CSS, css_bundle()) +} + +#[get("/assets/cantarell.woff2")] +pub fn r_assets_font() -> (ContentType, Vec<u8>) { +    (ContentType::WOFF2, font_bundle()) +} | 
