twilight_model/channel/message/component/
select_menu.rs

1use crate::channel::{ChannelType, message::EmojiReactionType};
2use crate::id::Id;
3use crate::id::marker::{ChannelMarker, RoleMarker, UserMarker};
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    /// Whether a selection is required in a modal.
38    ///
39    /// Ignored in messages.
40    pub required: Option<bool>,
41}
42
43/// A [`SelectMenu`]'s type.
44#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
45#[non_exhaustive]
46pub enum SelectMenuType {
47    /// Select menus with a text-based `options` list.
48    ///
49    /// Select menus of this `kind` *must* set the `options` field to specify the options users
50    /// can pick from.
51    Text,
52    /// User select menus.
53    User,
54    /// Role select menus.
55    Role,
56    /// Mentionable select menus.
57    Mentionable,
58    /// Channel select menus.
59    Channel,
60}
61
62/// Dropdown options that are part of [`SelectMenu`].
63#[derive(Clone, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
64pub struct SelectMenuOption {
65    /// Whether the option will be selected by default.
66    #[serde(default)]
67    pub default: bool,
68    /// Additional description.
69    #[serde(skip_serializing_if = "Option::is_none")]
70    pub description: Option<String>,
71    /// Emoji associated with the option. Appears left of the label and
72    /// description.
73    #[serde(skip_serializing_if = "Option::is_none")]
74    pub emoji: Option<EmojiReactionType>,
75    /// User-facing name.
76    pub label: String,
77    /// Developer defined value.
78    pub value: String,
79}
80
81/// A default value for an auto-populated select menu.
82#[derive(Copy, Clone, Debug, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize)]
83#[serde(tag = "type", content = "id", rename_all = "snake_case")]
84pub enum SelectDefaultValue {
85    /// Default user.
86    User(Id<UserMarker>),
87    /// Default role.
88    Role(Id<RoleMarker>),
89    /// Default channel.
90    Channel(Id<ChannelMarker>),
91}
92
93#[cfg(test)]
94mod tests {
95    use super::*;
96    use static_assertions::{assert_fields, assert_impl_all};
97    use std::{fmt::Debug, hash::Hash};
98
99    assert_fields!(
100        SelectMenu: channel_types,
101        custom_id,
102        default_values,
103        disabled,
104        kind,
105        max_values,
106        min_values,
107        options,
108        placeholder,
109        required
110    );
111    assert_impl_all!(SelectMenu: Clone, Debug, Eq, Hash, PartialEq, Send, Sync);
112
113    assert_impl_all!(
114        SelectMenuType: Clone,
115        Debug,
116        Eq,
117        Hash,
118        PartialEq,
119        Send,
120        Sync
121    );
122
123    assert_impl_all!(
124        SelectMenuOption: Clone,
125        Debug,
126        Deserialize<'static>,
127        Eq,
128        Hash,
129        PartialEq,
130        Send,
131        Serialize,
132        Sync
133    );
134    assert_fields!(SelectMenuOption: default, description, emoji, label, value);
135
136    assert_impl_all!(
137        SelectDefaultValue: Copy,
138        Clone,
139        Debug,
140        Deserialize<'static>,
141        Eq,
142        Hash,
143        Ord,
144        PartialEq,
145        PartialOrd,
146        Serialize
147    );
148}