use based::format::format_number; use based::ogp::{MediaItem, Metadata}; use based::request::respond_html; use based::ui::components::prelude::Shell; use based::ui::primitives::space::Fraction; use based::ui::{prelude::*, AttrExtendable}; use based::{ auth::MaybeUser, format::format_date, request::{RequestContext, StringResponse}, }; use maud::{html, PreEscaped, Render}; use rocket::{get, State}; use crate::config::Config; use crate::library::Video; use crate::{ library::{history::VideoHistory, Library}, pages::components::video_element_wide, }; use super::components::render_page; #[get("/watch?")] pub async fn watch_page( ctx: RequestContext, library: &State, v: String, user: MaybeUser, conf: &State, shell: &State, ) -> StringResponse { let video = if let Some(video) = library.get_video_by_id(&v).await { video } else { // TODO : Error handling library.get_video_by_youtube_id(&v).await.unwrap() }; let yt_meta = video.youtube_meta().await; let mut vid_meta = based::ogp::Video::Other(video.duration as u32, video.date_added.date_naive()); if let Some(yt_meta) = &yt_meta { for t in yt_meta.tags().await { vid_meta = vid_meta.tag(&t); } } let meta = Metadata::new( &format!("{}/watch?v={}", conf.general.root_url, video.id), &video.title, MediaItem::Image( &format!("{}/video/thumbnail?v={}", conf.general.root_url, video.id), "image/png", "Video Thumbnail", ), vid_meta, ) .site_name("WatchDogs"); if conf.general.private && user.user().is_none() { return respond_html( html! { (maud::DOCTYPE) html { head { (meta.render()) } body { } } } .0, ); } if let Some(user) = user.user() { user.insert_history(video.id).await; } let youtube_meta = video.youtube_meta().await; let rec = build_rec(&library, &video).await; let content = Margin( Screen::large(Flex(Nothing()).direction(Direction::Row)).on( Flex( Div().vanish() .push( Screen::large(Width(Fraction::_10on12, Nothing())).on( Div().push( Context(Aspect::Video( Background( Rounded( Width(ScreenValue::full, Video().controls().autoplay().width(1080).add_src( Source(&format!("/video/raw?v={}", video.id), Some("video/mp4".to_string())) ).poster(&format!("/video/thumbnail?v={}", video.id))) ).size(Size::Large) ).color(Colors::Black) )) ).push( Context(Margin(Padding( Background( Rounded( Shadow::large( Div() .push( Text(&video.title)._2xl().semibold() ) .push_some(youtube_meta.as_ref(), |meta: &_| { Div() .push( Context(Margin(Flex( Div().vanish().push( Margin(Text(&meta.uploader_name).color(&Gray::_300).xl()).bottom(ScreenValue::_4) ).push( Margin(Text(&format!("{} Views ﹣ {}", format_number(meta.views), format_date(&meta.upload_date))).color(&Gray::_300).xl()).bottom(ScreenValue::_4) ) ).justify(Justify::Between).group()).top(ScreenValue::_2)) ) .push( Context(Link(&format!("https://www.youtube.com/watch?v={}", meta.id), Text("Watch on YouTube").color(&Red::_400)) ) ).push( Context(Margin( Text(meta.description.trim_ascii()).sm().color(&Gray::_300).wrap(TextWrap::Pretty).whitespace(TextWhitespace::BreakSpaces) ).y(ScreenValue::_2).top(ScreenValue::_6) )) } ) )).size(Size::Large) ).color(Stone::_900) ).all(ScreenValue::_4)).top(ScreenValue::_8)) ) ) ).push( rec ) ).direction(Direction::Column).gap(ScreenValue::_6)) ).x(ScreenValue::_10).top(ScreenValue::_6).render(); render_page( &shell.inner().extend().metadata(meta), ctx, content, &format!("{} - WatchDogs", video.title), user.into(), ) .await } pub async fn build_rec(library: &Library, video: &Video) -> PreEscaped { let videos = library.get_directory_videos(&video.directory).await; let video_elements = html! { @for video in videos { (video_element_wide(&video).await); }; }; Width( Fraction::_1on3, Div() .id("recommendations") .push( Margin( Paragraph(Context( SpaceBetween( Flex( Div() .vanish() .push(Span("In ")._4xl().extrabold()) .push(Link( &format!("/d/{}", video.directory), Text(&video.directory) .color(&Blue::_500) ._4xl() .extrabold(), )), ) .group() .justify(Justify::Center), ) .x(ScreenValue::_2), )) .align(TextAlignment::Center) ._4xl() .extrabold(), ) .bottom(ScreenValue::_2), ) .push(video_elements), ) .render() }