Skip to content

Commit e8c5436

Browse files
authored
[Feature] Modal Select Components Support for IF (#3189)
* add interaction service attributes new modal input types * add new modal component type converters * relocate hide attribute outside of slash command enum converter for general purpose use * refactor base inputcomponentbuilder types to use modal component typeconverters * add builders for new modal input types * add component insertion methods to modal builder for new input types * refactor base inputcomponentinfo class to use modal component typeconverters * add component info classes for newly added modal input types * add build logic for new modal input metadata classes * add componet collection properties for new modal input types to modalinfo * implement convertion logic for new modal inputs to the respond with modal extension methods * implement modal input typeconverters into interaction service * add read logic to enum modal component typeconverter * add default entity modal component typeconverter * add write logic to default value modal component typeconverter * add write logic to the nullable modal component typeconverter * add description property to input label attribute * add inline docs to modal attributes * add modal file upload attribute * add inline docs to input component infos * add description property to input component builder * add inline docs to modal component builders * add modal file upload component info * add modal file upload component builder * rename select input attribute * refactor select input attribute and add description property in moduleClassBuilder * add inline docs to modalBuilder * add description to inputComponentInfo * file-scope namespace for commandBuilder and modal interfaces * update respondWithModal logic to include new components * add inline docs and file upload component to modalInfo * add attachment modal typeconverter * create base non-input modal component entities * update modal component typeconverter namespaces and remove unused * add default min/max values to select input attribute * create text display builder and info classes * add text display parsing logic * add text display attribute * add modal select menu option attribute * add docs to text display component info * fix text display parsing * add isRequired mapping to select menus * revert to block-scope to clear diff false-positives * fix inline doc annotations * fix build errors * add interaction parameter to modal component typeconverter write method * add null check to select menu option attribute * add null check to default value modalTypeConverter write method * make ctors of modal component base attributes internal * implement predicate to hide attribute and enum modalcomponent typeconverter * fix HideAttribute inline docs build errors * simplify naming of the component classes and normalize namespaces * fix build errors in module class builder * add inline docs to modalComponentTypeConverter TryGetModalInteractionData * add min/max values parameters to ModalChannelSelectAttribute * fix defaultArrayModalTypeConverter chanell type write logic * simplify addDefaultValue methods for channe, mentionable, role, and user selects * add emoji support to select menu options * add instance value parsing to enum modalComponentConverter
1 parent 06510e1 commit e8c5436

File tree

52 files changed

+2321
-327
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

52 files changed

+2321
-327
lines changed
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
using System;
2+
3+
namespace Discord.Interactions;
4+
5+
/// <summary>
6+
/// Enum values tagged with this attribute will not be displayed as a parameter choice
7+
/// </summary>
8+
/// <remarks>
9+
/// This attribute must be used along with the default <see cref="EnumConverter{T}"/> and <see cref="DefaultEntityTypeConverter{T}"/>.
10+
/// </remarks>
11+
[AttributeUsage(AttributeTargets.Field, AllowMultiple = false, Inherited = true)]
12+
public class HideAttribute : Attribute
13+
{
14+
/// <summary>
15+
/// Can be optionally implemented by inherited types to conditionally hide an enum value.
16+
/// </summary>
17+
/// <remarks>
18+
/// Only runs on prior to modal construction. For slash command parameters, this method is ignored.
19+
/// </remarks>
20+
/// <param name="interaction">Interaction that <see cref="IDiscordInteractionExtentions.RespondWithModalAsync{T}(IDiscordInteraction, string, T, RequestOptions, Action{ModalBuilder})"/> is called on.</param>
21+
/// <returns>
22+
/// <see langword="true"/> if the attribute should be active and hide the value.
23+
/// </returns>
24+
public virtual bool Predicate(IDiscordInteraction interaction) => true;
25+
}

src/Discord.Net.Interactions/Attributes/Modals/InputLabelAttribute.cs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,20 @@ public class InputLabelAttribute : Attribute
1313
/// </summary>
1414
public string Label { get; }
1515

16+
/// <summary>
17+
/// Gets the label description of the input.
18+
/// </summary>
19+
public string Description { get; set; }
20+
1621
/// <summary>
1722
/// Creates a custom label for an modal input.
1823
/// </summary>
1924
/// <param name="label">The label of the input.</param>
20-
public InputLabelAttribute(string label)
25+
/// <param name="description">The label description of the input.</param>
26+
public InputLabelAttribute(string label, string description = null)
2127
{
2228
Label = label;
29+
Description = description;
2330
}
2431
}
2532
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
namespace Discord.Interactions;
2+
3+
/// <summary>
4+
/// Marks a <see cref="IModal"/> property as a channel select.
5+
/// </summary>
6+
public class ModalChannelSelectAttribute : ModalSelectComponentAttribute
7+
{
8+
/// <inheritdoc/>
9+
public override ComponentType ComponentType => ComponentType.ChannelSelect;
10+
11+
/// <summary>
12+
/// Create a new <see cref="ModalChannelSelectAttribute"/>.
13+
/// </summary>
14+
/// <param name="customId">Custom ID of the channel select component.</param>
15+
public ModalChannelSelectAttribute(string customId, int minValues = 1, int maxValues = 1) : base(customId, minValues, maxValues) { }
16+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
using System;
2+
3+
namespace Discord.Interactions;
4+
5+
/// <summary>
6+
/// Mark an <see cref="IModal"/> property as a modal component field.
7+
/// </summary>
8+
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false, Inherited = false)]
9+
public abstract class ModalComponentAttribute : Attribute
10+
{
11+
/// <summary>
12+
/// Gets the type of the component.
13+
/// </summary>
14+
public abstract ComponentType ComponentType { get; }
15+
16+
internal ModalComponentAttribute() { }
17+
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
namespace Discord.Interactions;
2+
3+
/// <summary>
4+
/// Marks a <see cref="IModal"/> property as a file upload input.
5+
/// </summary>
6+
public class ModalFileUploadAttribute : ModalInputAttribute
7+
{
8+
/// <inheritdoc/>
9+
public override ComponentType ComponentType => ComponentType.FileUpload;
10+
11+
/// <summary>
12+
/// Get the minimum number of files that can be uploaded.
13+
/// </summary>
14+
public int MinValues { get; set; } = 1;
15+
16+
/// <summary>
17+
/// Get the maximum number of files that can be uploaded.
18+
/// </summary>
19+
public int MaxValues { get; set; } = 1;
20+
21+
/// <summary>
22+
/// Create a new <see cref="ModalFileUploadAttribute"/>.
23+
/// </summary>
24+
/// <param name="customId">Custom ID of the file upload component.</param>
25+
/// <param name="minValues">Minimum number of files that can be uploaded.</param>
26+
/// <param name="maxValues">Maximum number of files that can be uploaded.</param>
27+
public ModalFileUploadAttribute(string customId, int minValues = 1, int maxValues = 1) : base(customId)
28+
{
29+
MinValues = minValues;
30+
MaxValues = maxValues;
31+
}
32+
}

src/Discord.Net.Interactions/Attributes/Modals/ModalInputAttribute.cs

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,23 +6,18 @@ namespace Discord.Interactions
66
/// Mark an <see cref="IModal"/> property as a modal input field.
77
/// </summary>
88
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false, Inherited = false)]
9-
public abstract class ModalInputAttribute : Attribute
9+
public abstract class ModalInputAttribute : ModalComponentAttribute
1010
{
1111
/// <summary>
1212
/// Gets the custom id of the text input.
1313
/// </summary>
1414
public string CustomId { get; }
1515

16-
/// <summary>
17-
/// Gets the type of the component.
18-
/// </summary>
19-
public abstract ComponentType ComponentType { get; }
20-
2116
/// <summary>
2217
/// Create a new <see cref="ModalInputAttribute"/>.
2318
/// </summary>
2419
/// <param name="customId">The custom id of the input.</param>
25-
protected ModalInputAttribute(string customId)
20+
internal ModalInputAttribute(string customId)
2621
{
2722
CustomId = customId;
2823
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
namespace Discord.Interactions;
2+
3+
/// <summary>
4+
/// Marks a <see cref="IModal"/> property as a mentionable select input.
5+
/// </summary>
6+
public class ModalMentionableSelectAttribute : ModalSelectComponentAttribute
7+
{
8+
/// <inheritdoc />
9+
public override ComponentType ComponentType => ComponentType.MentionableSelect;
10+
11+
/// <summary>
12+
/// Create a new <see cref="ModalMentionableSelectAttribute"/>.
13+
/// </summary>
14+
/// <param name="customId">Custom ID of the mentionable select component.</param>
15+
/// <param name="minValues">Minimum number of values that can be selected.</param>
16+
/// <param name="maxValues">Maximum number of values that can be selected</param>
17+
public ModalMentionableSelectAttribute(string customId, int minValues = 1, int maxValues = 1) : base(customId, minValues, maxValues) { }
18+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
namespace Discord.Interactions;
2+
3+
/// <summary>
4+
/// Marks a <see cref="IModal"/> property as a role select input.
5+
/// </summary>
6+
public class ModalRoleSelectAttribute : ModalSelectComponentAttribute
7+
{
8+
/// <inheritdoc/>
9+
public override ComponentType ComponentType => ComponentType.RoleSelect;
10+
11+
/// <summary>
12+
/// Create a new <see cref="ModalRoleSelectAttribute"/>.
13+
/// </summary>
14+
/// <param name="customId">Custom ID of the role select component.</param>
15+
/// <param name="minValues">Minimum number of values that can be selected.</param>
16+
/// <param name="maxValues">Maximum number of values that can be selected.</param>
17+
public ModalRoleSelectAttribute(string customId, int minValues = 1, int maxValues = 1) : base(customId, minValues, maxValues) { }
18+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
namespace Discord.Interactions;
2+
3+
/// <summary>
4+
/// Base attribute for select-menu, user, channel, role, and mentionable select inputs in modals.
5+
/// </summary>
6+
public abstract class ModalSelectComponentAttribute : ModalInputAttribute
7+
{
8+
/// <summary>
9+
/// Gets or sets the minimum number of values that can be selected.
10+
/// </summary>
11+
public int MinValues { get; set; } = 1;
12+
13+
/// <summary>
14+
/// Gets or sets the maximum number of values that can be selected.
15+
/// </summary>
16+
public int MaxValues { get; set; } = 1;
17+
18+
/// <summary>
19+
/// Gets or sets the placeholder text.
20+
/// </summary>
21+
public string Placeholder { get; set; }
22+
23+
internal ModalSelectComponentAttribute(string customId, int minValues = 1, int maxValues = 1) : base(customId)
24+
{
25+
MinValues = minValues;
26+
MaxValues = maxValues;
27+
}
28+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
namespace Discord.Interactions;
2+
3+
/// <summary>
4+
/// Marks a <see cref="IModal"/> property as a select menu input.
5+
/// </summary>
6+
public sealed class ModalSelectMenuAttribute : ModalSelectComponentAttribute
7+
{
8+
/// <inheritdoc />
9+
public override ComponentType ComponentType => ComponentType.SelectMenu;
10+
11+
/// <summary>
12+
/// Create a new <see cref="ModalSelectMenuAttribute"/>.
13+
/// </summary>
14+
/// <param name="customId">Custom ID of the select menu component.</param>
15+
/// <param name="minValues">Minimum number of values that can be selected.</param>
16+
/// <param name="maxValues">Maximum number of values that can be selected.</param>
17+
public ModalSelectMenuAttribute(string customId, int minValues = 1, int maxValues = 1) : base(customId, minValues, maxValues) { }
18+
}

0 commit comments

Comments
 (0)