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