twilight_model/channel/message/component/
select_menu.rs

1use crate::channel::{message::EmojiReactionType, ChannelType};
2use crate::id::marker::{ChannelMarker, RoleMarker, UserMarker};
3use crate::id::Id;
4use serde::{Deserialize, Serialize};
5
6/// Dropdown-style [`Component`] that renders below messages.
7///
8/// [`Component`]: super::Component
9#[derive(Clone, Debug, Eq, Hash, PartialEq)]
10pub struct SelectMenu {
11    /// Optional identifier for this select menu.
12    pub id: Option<i32>,
13    /// An optional list of channel types.
14    ///
15    /// This is only applicable to [channel select menus](SelectMenuType::Channel).
16    pub channel_types: Option<Vec<ChannelType>>,
17    /// Developer defined identifier.
18    pub custom_id: String,
19    /// List of default values for auto-populated select menus.
20    pub default_values: Option<Vec<SelectDefaultValue>>,
21    /// Whether the select menu is disabled.
22    ///
23    /// Defaults to `false`.
24    pub disabled: bool,
25    /// This select menu's type.
26    pub kind: SelectMenuType,
27    /// Maximum number of options that may be chosen.
28    pub max_values: Option<u8>,
29    /// Minimum number of options that must be chosen.
30    pub min_values: Option<u8>,
31    /// A list of available options.
32    ///
33    /// This is required by [text select menus](SelectMenuType::Text).
34    pub options: Option<Vec<SelectMenuOption>>,
35    /// Custom placeholder text if no option is selected.
36    pub placeholder: Option<String>,
37}
38
39/// A [`SelectMenu`]'s type.
40#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
41#[non_exhaustive]
42pub enum SelectMenuType {
43    /// Select menus with a text-based `options` list.
44    ///
45    /// Select menus of this `kind` *must* set the `options` field to specify the options users
46    /// can pick from.
47    Text,
48    /// User select menus.
49    User,
50    /// Role select menus.
51    Role,
52    /// Mentionable select menus.
53    Mentionable,
54    /// Channel select menus.
55    Channel,
56}
57
58/// Dropdown options that are part of [`SelectMenu`].
59#[derive(Clone, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
60pub struct SelectMenuOption {
61    /// Whether the option will be selected by default.
62    #[serde(default)]
63    pub default: bool,
64    /// Additional description.
65    #[serde(skip_serializing_if = "Option::is_none")]
66    pub description: Option<String>,
67    /// Emoji associated with the option. Appears left of the label and
68    /// description.
69    #[serde(skip_serializing_if = "Option::is_none")]
70    pub emoji: Option<EmojiReactionType>,
71    /// User-facing name.
72    pub label: String,
73    /// Developer defined value.
74    pub value: String,
75}
76
77/// A default value for an auto-populated select menu.
78#[derive(Copy, Clone, Debug, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize)]
79#[serde(tag = "type", content = "id", rename_all = "snake_case")]
80pub enum SelectDefaultValue {
81    /// Default user.
82    User(Id<UserMarker>),
83    /// Default role.
84    Role(Id<RoleMarker>),
85    /// Default channel.
86    Channel(Id<ChannelMarker>),
87}
88
89#[cfg(test)]
90mod tests {
91    use super::*;
92    use static_assertions::{assert_fields, assert_impl_all};
93    use std::{fmt::Debug, hash::Hash};
94
95    assert_fields!(
96        SelectMenu: channel_types,
97        custom_id,
98        default_values,
99        disabled,
100        kind,
101        max_values,
102        min_values,
103        options,
104        placeholder
105    );
106    assert_impl_all!(SelectMenu: Clone, Debug, Eq, Hash, PartialEq, Send, Sync);
107
108    assert_impl_all!(
109        SelectMenuType: Clone,
110        Debug,
111        Eq,
112        Hash,
113        PartialEq,
114        Send,
115        Sync
116    );
117
118    assert_impl_all!(
119        SelectMenuOption: Clone,
120        Debug,
121        Deserialize<'static>,
122        Eq,
123        Hash,
124        PartialEq,
125        Send,
126        Serialize,
127        Sync
128    );
129    assert_fields!(SelectMenuOption: default, description, emoji, label, value);
130
131    assert_impl_all!(
132        SelectDefaultValue: Copy,
133        Clone,
134        Debug,
135        Deserialize<'static>,
136        Eq,
137        Hash,
138        Ord,
139        PartialEq,
140        PartialOrd,
141        Serialize
142    );
143}