227 lines
6.3 KiB
Rust
227 lines
6.3 KiB
Rust
use based::page;
|
|
use based::request::respond_html;
|
|
use based::ui::components::prelude::{InfinityScroll, Shell};
|
|
use based::ui::components::ColoredSpinner;
|
|
use based::ui::prelude::*;
|
|
use based::ui::primitives::div::Center;
|
|
use based::{
|
|
auth::MaybeUser,
|
|
request::{
|
|
api::{vec_to_api, FallibleApiResponse},
|
|
RequestContext, StringResponse,
|
|
},
|
|
};
|
|
use maud::{html, PreEscaped, Render};
|
|
use rocket::{get, State};
|
|
use serde_json::json;
|
|
|
|
use crate::config::Config;
|
|
use crate::library::Video;
|
|
use crate::pages::components::{Title, VerticalVideoGrid, VerticalVideoGridRaw};
|
|
use crate::{library::Library, pages::components::video_element};
|
|
|
|
use super::components::DirectoryBadge;
|
|
use super::{
|
|
api_response,
|
|
components::{render_page, video_element_wide},
|
|
};
|
|
|
|
#[macro_export]
|
|
macro_rules! check_private {
|
|
($conf:ident, $user:ident, $shell:ident, $ctx:ident) => {
|
|
if $conf.general.private && $user.user().is_none() {
|
|
return $crate::pages::index::is_private_page($shell, $ctx).await;
|
|
}
|
|
};
|
|
}
|
|
|
|
#[get("/search?<query>&<offset>")]
|
|
pub async fn search(
|
|
query: &str,
|
|
offset: Option<i64>,
|
|
library: &State<Library>,
|
|
conf: &State<Config>,
|
|
user: MaybeUser,
|
|
shell: &State<Shell>,
|
|
ctx: RequestContext,
|
|
) -> Option<serde_json::Value> {
|
|
// todo : check_private!(conf, user, shell, ctx);
|
|
|
|
const NUM_OF_RESULTS: i64 = 20;
|
|
|
|
// get start parameter for search result chunks
|
|
let start = offset.unwrap_or(0);
|
|
|
|
let mut video_matches = library.search_video(query, start, NUM_OF_RESULTS).await;
|
|
|
|
Some(json!(vec_to_api(&mut video_matches).await))
|
|
}
|
|
|
|
#[get("/latest.json")]
|
|
pub async fn latest_api(
|
|
library: &State<Library>,
|
|
user: MaybeUser,
|
|
conf: &State<Config>,
|
|
shell: &State<Shell>,
|
|
ctx: RequestContext,
|
|
) -> FallibleApiResponse {
|
|
// todo : check_private!(conf, user, shell, ctx);
|
|
|
|
let videos = library.get_newly_added(24, 0).await;
|
|
let vid_api = vec_to_api(&videos).await;
|
|
return Ok(serde_json::json!(vid_api));
|
|
}
|
|
|
|
#[allow(non_snake_case)]
|
|
pub async fn VideoList(videos: &[Video]) -> PreEscaped<String> {
|
|
let video_elements = html! {
|
|
@for mut vid in videos {
|
|
( video_element_wide(&mut vid).await );
|
|
};
|
|
};
|
|
|
|
Padding(video_elements).all(ScreenValue::_6).render()
|
|
}
|
|
|
|
#[get("/latest?<offset>")]
|
|
pub async fn latest_page(
|
|
ctx: RequestContext,
|
|
library: &State<Library>,
|
|
user: MaybeUser,
|
|
shell: &State<Shell>,
|
|
conf: &State<Config>,
|
|
offset: Option<u32>,
|
|
) -> StringResponse {
|
|
check_private!(conf, user, shell, ctx);
|
|
|
|
let mut videos: Vec<_> = library
|
|
.get_newly_added(21, offset.unwrap_or_default() as i64)
|
|
.await;
|
|
let has_content = !videos.is_empty();
|
|
let video_elements = VerticalVideoGrid(&mut videos).await;
|
|
|
|
if ctx.is_htmx && !ctx.htmx_redirect {
|
|
return respond_html(
|
|
Div()
|
|
.vanish()
|
|
.push(video_elements)
|
|
.push_if(has_content, || {
|
|
Width(
|
|
ScreenValue::fit,
|
|
Margin(InfinityScroll(
|
|
ColoredSpinner(Purple::_600),
|
|
&format!("/latest?offset={}", offset.unwrap_or_default() + 21),
|
|
))
|
|
.x(ScreenValue::auto),
|
|
)
|
|
})
|
|
.render()
|
|
.0,
|
|
);
|
|
}
|
|
|
|
let content = Div()
|
|
.vanish()
|
|
.push(Title("Recent videos"))
|
|
.push(video_elements)
|
|
.push(Width(
|
|
ScreenValue::fit,
|
|
Margin(InfinityScroll(
|
|
ColoredSpinner(Purple::_600),
|
|
&format!("/latest?offset={}", offset.unwrap_or_default() + 21),
|
|
))
|
|
.x(ScreenValue::auto),
|
|
))
|
|
.render();
|
|
|
|
render_page(&shell, ctx, content, "Recent videos", user.into()).await
|
|
}
|
|
|
|
#[get("/d/<dir>")]
|
|
pub async fn dir_page(
|
|
ctx: RequestContext,
|
|
dir: &str,
|
|
library: &State<Library>,
|
|
user: MaybeUser,
|
|
shell: &State<Shell>,
|
|
conf: &State<Config>,
|
|
) -> StringResponse {
|
|
check_private!(conf, user, shell, ctx);
|
|
|
|
if dir.ends_with(".json") {
|
|
let dir_videos = library
|
|
.get_directory_videos(dir.split_once(".json").map(|x| x.0).unwrap_or_default())
|
|
.await;
|
|
return api_response(&json!(vec_to_api(&dir_videos).await));
|
|
}
|
|
|
|
let dir_videos = library.get_directory_videos(dir).await;
|
|
let video_elements = html! {
|
|
@for mut vid in dir_videos {
|
|
( video_element_wide(&mut vid).await );
|
|
};
|
|
};
|
|
|
|
let content = Div()
|
|
.vanish()
|
|
.push(Title(dir.to_string()))
|
|
.push(Padding(video_elements).all(ScreenValue::_6))
|
|
.render();
|
|
|
|
render_page(&shell, ctx, content, dir, user.into()).await
|
|
}
|
|
|
|
pub async fn is_private_page(shell: &Shell, ctx: RequestContext) -> StringResponse {
|
|
page!(
|
|
shell,
|
|
ctx,
|
|
"WatchDogs",
|
|
Margin(Center(Text("This is a private instance").bold()._4xl())).top(ScreenValue::_12)
|
|
)
|
|
}
|
|
|
|
#[get("/")]
|
|
pub async fn index_page(
|
|
ctx: RequestContext,
|
|
library: &State<Library>,
|
|
user: MaybeUser,
|
|
shell: &State<Shell>,
|
|
conf: &State<Config>,
|
|
) -> StringResponse {
|
|
check_private!(conf, user, shell, ctx);
|
|
|
|
let random_video_elements = html! {
|
|
@for mut vid in library.get_random_videos(3).await {
|
|
( video_element(&mut vid).await );
|
|
};
|
|
};
|
|
let newly_added_elements = html! {
|
|
@for mut vid in library.get_newly_added(3, 0).await {
|
|
( video_element(&mut vid).await );
|
|
};
|
|
};
|
|
let directories = library.get_directories().await;
|
|
|
|
let content = Div()
|
|
.vanish()
|
|
.push(Title("Random Videos"))
|
|
.push(VerticalVideoGridRaw(random_video_elements))
|
|
.push(Title(Link("/latest", "Latest Videos").use_htmx()))
|
|
.push(VerticalVideoGridRaw(newly_added_elements))
|
|
.push(Title("Directories:"))
|
|
.push(
|
|
Padding(
|
|
Flex(
|
|
Div()
|
|
.vanish()
|
|
.push_for_each(&directories, |dir: &_| DirectoryBadge(dir)),
|
|
)
|
|
.wrap(Wrap::Wrap)
|
|
.justify(Justify::Evenly),
|
|
)
|
|
.all(ScreenValue::_10),
|
|
)
|
|
.render();
|
|
|
|
render_page(&shell, ctx, content, "WatchDogs", user.into()).await
|
|
}
|