use std::borrow::Cow;
use serde::{Deserialize, Serialize};
#[cfg(feature = "validation")]
use validator::Validate;
#[cfg(feature = "validation")]
use crate::val_helpr::ValidationResult;
use crate::{compose::Confirm, text};
#[derive(Clone, Debug, Deserialize, Hash, PartialEq, Serialize)]
#[cfg_attr(feature = "validation", derive(Validate))]
pub struct Button<'a> {
#[cfg_attr(feature = "validation", validate(custom = "validate::text"))]
text: text::Text,
#[cfg_attr(feature = "validation", validate(length(max = 255)))]
action_id: Cow<'a, str>,
#[serde(skip_serializing_if = "Option::is_none")]
#[cfg_attr(feature = "validation", validate(custom = "validate::url"))]
url: Option<Cow<'a, str>>,
#[serde(skip_serializing_if = "Option::is_none")]
#[cfg_attr(feature = "validation", validate(custom = "validate::value"))]
value: Option<Cow<'a, str>>,
#[serde(skip_serializing_if = "Option::is_none")]
style: Option<Style>,
#[serde(skip_serializing_if = "Option::is_none")]
#[cfg_attr(feature = "validation", validate)]
confirm: Option<Confirm>,
}
impl<'a> Button<'a> {
pub fn builder() -> build::ButtonBuilderInit<'a> {
build::ButtonBuilderInit::new()
}
#[cfg(feature = "validation")]
#[cfg_attr(docsrs, doc(cfg(feature = "validation")))]
pub fn validate(&self) -> ValidationResult {
Validate::validate(self)
}
}
#[derive(Copy, Clone, Debug, Deserialize, Hash, PartialEq, Serialize)]
#[serde(rename_all = "snake_case")]
pub enum Style {
Primary,
Danger,
}
pub mod build {
use std::marker::PhantomData;
use super::*;
use crate::build::*;
#[allow(non_camel_case_types)]
pub mod method {
#[derive(Copy, Clone, Debug)]
pub struct text;
#[derive(Copy, Clone, Debug)]
pub struct action_id;
}
pub type ButtonBuilderInit<'a> =
ButtonBuilder<'a,
RequiredMethodNotCalled<method::text>,
RequiredMethodNotCalled<method::action_id>>;
#[derive(Debug)]
pub struct ButtonBuilder<'a, Text, ActionId> {
text: Option<text::Text>,
action_id: Option<Cow<'a, str>>,
url: Option<Cow<'a, str>>,
value: Option<Cow<'a, str>>,
style: Option<Style>,
confirm: Option<Confirm>,
state: PhantomData<(Text, ActionId)>,
}
impl<'a, T, A> ButtonBuilder<'a, T, A> {
pub fn new() -> Self {
Self { text: None,
action_id: None,
url: None,
value: None,
style: None,
confirm: None,
state: PhantomData::<_> }
}
pub fn style(mut self, style: Style) -> Self {
self.style = Some(style);
self
}
pub fn confirm(mut self, confirm: Confirm) -> Self {
self.confirm = Some(confirm);
self
}
pub fn url(mut self, url: impl Into<Cow<'a, str>>) -> Self {
self.url = Some(url.into());
self
}
pub fn value(mut self, value: impl Into<Cow<'a, str>>) -> Self {
self.value = Some(value.into());
self
}
pub fn action_id(self,
action_id: impl Into<Cow<'a, str>>)
-> ButtonBuilder<'a, T, Set<method::action_id>> {
ButtonBuilder { text: self.text,
action_id: Some(action_id.into()),
url: self.url,
value: self.value,
style: self.style,
confirm: self.confirm,
state: PhantomData::<_> }
}
#[cfg(feature = "blox")]
#[cfg_attr(docsrs, doc(cfg(feature = "blox")))]
pub fn child(self,
text: impl Into<text::Plain>)
-> ButtonBuilder<'a, Set<method::text>, A> {
self.text(text)
}
pub fn text(self,
text: impl Into<text::Plain>)
-> ButtonBuilder<'a, Set<method::text>, A> {
ButtonBuilder { text: Some(text.into().into()),
action_id: self.action_id,
url: self.url,
value: self.value,
style: self.style,
confirm: self.confirm,
state: PhantomData::<_> }
}
}
impl<'a> ButtonBuilder<'a, Set<method::text>, Set<method::action_id>> {
pub fn build(self) -> Button<'a> {
Button { text: self.text.unwrap(),
action_id: self.action_id.unwrap(),
url: self.url,
confirm: self.confirm,
style: self.style,
value: self.value }
}
}
}
#[cfg(feature = "validation")]
mod validate {
use super::*;
use crate::{text,
val_helpr::{below_len, ValidatorResult}};
pub(super) fn text(text: &text::Text) -> ValidatorResult {
below_len("Button Text", 75, text.as_ref())
}
pub(super) fn url(url: &Cow<str>) -> ValidatorResult {
below_len("Button.url", 3000, url)
}
pub(super) fn value(value: &Cow<str>) -> ValidatorResult {
below_len("Button.text", 2000, value)
}
}