1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125
use crate::channel::message::ReactionType;
use serde::{Deserialize, Serialize};
/// Clickable [`Component`] below messages.
///
/// [`Component`]: super::Component
#[derive(Clone, Debug, Eq, Hash, PartialEq)]
pub struct Button {
/// User defined identifier for the button.
///
/// This field is required when using the following [`ButtonStyle`]s:
///
/// - [`ButtonStyle::Danger`]
/// - [`ButtonStyle::Primary`]
/// - [`ButtonStyle::Secondary`]
/// - [`ButtonStyle::Success`]
pub custom_id: Option<String>,
/// Whether the button is disabled.
///
/// Defaults to `false`.
pub disabled: bool,
/// Visual emoji for clients to display with the button.
pub emoji: Option<ReactionType>,
/// Text appearing on the button.
pub label: Option<String>,
/// Style variant of the button.
pub style: ButtonStyle,
/// URL for buttons of a [`ButtonStyle::Link`] style.
pub url: Option<String>,
}
/// Style of a [`Button`].
// Keep in sync with `twilight-validate::component`!
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
#[non_exhaustive]
#[serde(from = "u8", into = "u8")]
pub enum ButtonStyle {
/// Button indicates a primary action.
///
/// Selecting this button style requires specifying the
/// [`Button::custom_id`] field.
Primary,
/// Button indicates a secondary action.
///
/// Selecting this button style requires specifying the
/// [`Button::custom_id`] field.
Secondary,
/// Button indicates a successful action.
///
/// Selecting this button style requires specifying the
/// [`Button::custom_id`] field.
Success,
/// Button indicates a dangerous action.
///
/// Selecting this button style requires specifying the
/// [`Button::custom_id`] field.
Danger,
/// Button indicates an action with a link.
///
/// Selecting this button style requires specifying the [`Button::url`]
/// field.
Link,
/// Variant value is unknown to the library.
Unknown(u8),
}
impl From<u8> for ButtonStyle {
fn from(value: u8) -> Self {
match value {
1 => ButtonStyle::Primary,
2 => ButtonStyle::Secondary,
3 => ButtonStyle::Success,
4 => ButtonStyle::Danger,
5 => ButtonStyle::Link,
unknown => ButtonStyle::Unknown(unknown),
}
}
}
impl From<ButtonStyle> for u8 {
fn from(value: ButtonStyle) -> Self {
match value {
ButtonStyle::Primary => 1,
ButtonStyle::Secondary => 2,
ButtonStyle::Success => 3,
ButtonStyle::Danger => 4,
ButtonStyle::Link => 5,
ButtonStyle::Unknown(unknown) => unknown,
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use serde_test::Token;
use static_assertions::{assert_fields, assert_impl_all};
use std::{fmt::Debug, hash::Hash};
assert_fields!(Button: custom_id, disabled, emoji, label, style, url);
assert_impl_all!(Button: Clone, Debug, Eq, Hash, PartialEq, Send, Sync);
assert_impl_all!(
ButtonStyle: Clone,
Copy,
Debug,
Deserialize<'static>,
Eq,
Hash,
PartialEq,
Send,
Serialize,
Sync
);
#[test]
fn button_style() {
serde_test::assert_tokens(&ButtonStyle::Primary, &[Token::U8(1)]);
serde_test::assert_tokens(&ButtonStyle::Secondary, &[Token::U8(2)]);
serde_test::assert_tokens(&ButtonStyle::Success, &[Token::U8(3)]);
serde_test::assert_tokens(&ButtonStyle::Danger, &[Token::U8(4)]);
serde_test::assert_tokens(&ButtonStyle::Link, &[Token::U8(5)]);
serde_test::assert_tokens(&ButtonStyle::Unknown(99), &[Token::U8(99)]);
}
}