279 lines
5.7 KiB
Rust
279 lines
5.7 KiB
Rust
use crate::ui::UIWidget;
|
|
use maud::{Markup, PreEscaped, Render, html};
|
|
|
|
#[allow(non_snake_case)]
|
|
#[must_use]
|
|
pub fn Image(src: &str) -> ImageWidget {
|
|
ImageWidget {
|
|
src: src.to_owned(),
|
|
alt: String::new(),
|
|
width: None,
|
|
height: None,
|
|
caption: None,
|
|
}
|
|
}
|
|
|
|
pub struct ImageWidget {
|
|
src: String,
|
|
alt: String,
|
|
width: Option<u32>,
|
|
height: Option<u32>,
|
|
caption: Option<String>,
|
|
}
|
|
|
|
impl Render for ImageWidget {
|
|
fn render(&self) -> Markup {
|
|
self.render_with_class("")
|
|
}
|
|
}
|
|
|
|
impl ImageWidget {
|
|
#[must_use]
|
|
pub fn alt(mut self, alt: &str) -> Self {
|
|
self.alt = alt.to_string();
|
|
self
|
|
}
|
|
|
|
#[must_use]
|
|
pub fn width(mut self, width: u32) -> Self {
|
|
self.width = Some(width);
|
|
self
|
|
}
|
|
|
|
#[must_use]
|
|
pub fn height(mut self, height: u32) -> Self {
|
|
self.height = Some(height);
|
|
self
|
|
}
|
|
|
|
#[must_use]
|
|
pub fn caption(mut self, caption: &str) -> Self {
|
|
self.caption = Some(caption.to_string());
|
|
self
|
|
}
|
|
|
|
pub fn build_img(&self, class: &str) -> PreEscaped<String> {
|
|
let mut str = "<img".to_string();
|
|
|
|
str.push_str(&format!(" src=\"{}\"", self.src));
|
|
|
|
if !self.alt.is_empty() {
|
|
str.push_str(&format!(" alt=\"{}\"", self.alt));
|
|
}
|
|
|
|
if let Some(width) = self.width {
|
|
str.push_str(&format!(" width=\"{width}\""));
|
|
}
|
|
|
|
if let Some(height) = self.height {
|
|
str.push_str(&format!(" height=\"{height}\""));
|
|
}
|
|
|
|
str.push_str(&format!(" class=\"{class}\">"));
|
|
|
|
PreEscaped(str)
|
|
}
|
|
}
|
|
|
|
impl UIWidget for ImageWidget {
|
|
fn can_inherit(&self) -> bool {
|
|
true
|
|
}
|
|
|
|
fn base_class(&self) -> Vec<String> {
|
|
vec![]
|
|
}
|
|
|
|
fn extended_class(&self) -> Vec<String> {
|
|
self.base_class()
|
|
}
|
|
|
|
fn render_with_class(&self, class: &str) -> Markup {
|
|
if let Some(caption) = &self.caption {
|
|
return html! {
|
|
figure class="w-fit" {
|
|
(self.build_img(class))
|
|
figcaption class="mt-2 text-sm text-center text-gray-500 dark:text-gray-400" { (caption) };
|
|
}
|
|
};
|
|
}
|
|
|
|
self.build_img(class)
|
|
}
|
|
}
|
|
|
|
#[allow(non_snake_case)]
|
|
#[must_use]
|
|
pub fn Video() -> VideoWidget {
|
|
VideoWidget {
|
|
src: Vec::new(),
|
|
controls: false,
|
|
autoplay: false,
|
|
looping: false,
|
|
muted: false,
|
|
poster: None,
|
|
width: None,
|
|
height: None,
|
|
}
|
|
}
|
|
|
|
pub struct VideoWidget {
|
|
src: Vec<SourceWidget>,
|
|
controls: bool,
|
|
autoplay: bool,
|
|
looping: bool,
|
|
muted: bool,
|
|
poster: Option<String>,
|
|
width: Option<u32>,
|
|
height: Option<u32>,
|
|
}
|
|
|
|
impl Render for VideoWidget {
|
|
fn render(&self) -> Markup {
|
|
self.render_with_class("")
|
|
}
|
|
}
|
|
|
|
impl VideoWidget {
|
|
pub fn add_src(mut self, src: SourceWidget) -> Self {
|
|
self.src.push(src);
|
|
self
|
|
}
|
|
|
|
pub fn controls(mut self) -> Self {
|
|
self.controls = true;
|
|
self
|
|
}
|
|
|
|
pub fn autoplay(mut self) -> Self {
|
|
self.autoplay = true;
|
|
self
|
|
}
|
|
|
|
pub fn looping(mut self) -> Self {
|
|
self.looping = true;
|
|
self
|
|
}
|
|
|
|
pub fn muted(mut self) -> Self {
|
|
self.muted = true;
|
|
self
|
|
}
|
|
|
|
pub fn poster(mut self, poster: &str) -> Self {
|
|
self.poster = Some(poster.to_string());
|
|
self
|
|
}
|
|
|
|
pub fn width(mut self, w: u32) -> Self {
|
|
self.width = Some(w);
|
|
self
|
|
}
|
|
|
|
pub fn height(mut self, h: u32) -> Self {
|
|
self.height = Some(h);
|
|
self
|
|
}
|
|
}
|
|
|
|
impl UIWidget for VideoWidget {
|
|
fn can_inherit(&self) -> bool {
|
|
true
|
|
}
|
|
|
|
fn base_class(&self) -> Vec<String> {
|
|
vec![]
|
|
}
|
|
|
|
fn extended_class(&self) -> Vec<String> {
|
|
self.base_class()
|
|
}
|
|
|
|
fn render_with_class(&self, class: &str) -> Markup {
|
|
let mut ret = "<video".to_string();
|
|
|
|
if self.controls {
|
|
ret.push_str(" controls");
|
|
}
|
|
|
|
if self.autoplay {
|
|
ret.push_str(" autoplay");
|
|
}
|
|
|
|
if self.looping {
|
|
ret.push_str(" loop");
|
|
}
|
|
|
|
if self.muted {
|
|
ret.push_str(" muted");
|
|
}
|
|
|
|
if let Some(poster) = &self.poster {
|
|
ret.push_str(&format!(" poster=\"{}\"", poster.replace("\"", "\\\"")));
|
|
}
|
|
|
|
if let Some(w) = &self.width {
|
|
ret.push_str(&format!(" width=\"{}\"", w));
|
|
}
|
|
|
|
if let Some(h) = &self.height {
|
|
ret.push_str(&format!(" height=\"{}\"", h));
|
|
}
|
|
|
|
ret.push_str(&format!(" class=\"{class}\""));
|
|
|
|
ret.push_str("> ");
|
|
|
|
for src in &self.src {
|
|
ret.push_str(&src.render().0);
|
|
}
|
|
|
|
ret.push_str("\nYour browser does not support the video tag.\n</video>");
|
|
|
|
PreEscaped(ret)
|
|
}
|
|
}
|
|
|
|
#[allow(non_snake_case)]
|
|
#[must_use]
|
|
pub fn Source(src: &str, mime: Option<String>) -> SourceWidget {
|
|
SourceWidget {
|
|
src: src.to_owned(),
|
|
mime,
|
|
}
|
|
}
|
|
|
|
pub struct SourceWidget {
|
|
src: String,
|
|
mime: Option<String>,
|
|
}
|
|
|
|
impl Render for SourceWidget {
|
|
fn render(&self) -> Markup {
|
|
self.render_with_class("")
|
|
}
|
|
}
|
|
|
|
impl UIWidget for SourceWidget {
|
|
fn can_inherit(&self) -> bool {
|
|
false
|
|
}
|
|
|
|
fn base_class(&self) -> Vec<String> {
|
|
vec![]
|
|
}
|
|
|
|
fn extended_class(&self) -> Vec<String> {
|
|
self.base_class()
|
|
}
|
|
|
|
fn render_with_class(&self, _: &str) -> Markup {
|
|
html! {
|
|
@if let Some(mime) = &self.mime {
|
|
source src=(self.src) type=(mime);
|
|
} @else {
|
|
source src=(self.src);
|
|
};
|
|
}
|
|
}
|
|
}
|