twilight_model/channel/message/component/button.rs
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 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142
use crate::{
channel::message::EmojiReactionType,
id::{marker::SkuMarker, Id},
};
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<EmojiReactionType>,
/// 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>,
/// The ID of the SKU that is attached to the button.
///
/// This field is required when using the [`ButtonStyle::Premium`] style.
pub sku_id: Option<Id<SkuMarker>>,
}
/// 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,
/// Button indicates a premium upgrade action.
///
/// Selecting this button style requires specifying the [`Button::sku_id`]
/// field.
/// The following fields are not available for this button style: [`Button::custom_id`], [`Button::label`], [`Button::url`] & [`Button::emoji`].
/// Premium button styles do not fire an interaction event.
Premium,
/// 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,
6 => ButtonStyle::Premium,
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::Premium => 6,
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::Premium, &[Token::U8(6)]);
serde_test::assert_tokens(&ButtonStyle::Unknown(99), &[Token::U8(99)]);
}
}