Skip to content

Commit c8f175e

Browse files
quinchsCottageDwellingCatCenngolhjt
authored
Feature: Implement modals (#2087)
* Implement Modals (#428) * Socket Modal Support * fix shareded client support * Properly use `HasResponded` instead of `_hasResponded` * `ModalBuilder` and `TextInputBuilder` validation. * make orginisation more consistant. * Rest Modals. * Docs + add missing methods * fix message signatures and missing abstract members * modal changes * um????? * update modal docs * update docs - again for some reason * cleanup * fix message signatures * add modal commands support to interaction service * Fix _hasResponded * update to new unsupported standard. * Sending modals with Interaction service. * fix spelling in ComponentBuilder * sending IModals when responding to interactions * interaction service modals * fix rest modals * spelling and minor improvements. * improve interaction service modal proformance * use precompiled lambda for interaction service modals * respect user compiled lambda choice * changes to modals in the interaction service (more) * support compiled lambdas in modal properties. * modal interactions tweaks * fix inline doc * more modal docs * configure responce to faild modal component * init * solve runtime errors * solve build errors * add default value parsing * make modal info caching static * make ModalUtils static * add inline docs * fix build errors * code cleanup * Introduce Required and Label properties as seperate attributes. * replace internal dictionary of ModalInfo with a list * change input building logic of modals * update RespondWithModalAsync method * add initial value parameter back to ModalTextInput and fix optional modal field * add missing inline docs * dispose the reference modal instance after building * code cleanup on modalcommandbuilder * Update docs/guides/int_basics/message-components/text-input.md Co-authored-by: Jared L <[email protected]> * Update docs/guides/int_basics/message-components/text-input.md Co-authored-by: Jared L <[email protected]> * Update docs/guides/int_basics/modals/intro.md Co-authored-by: Jared L <[email protected]> * Update docs/guides/int_basics/modals/intro.md Co-authored-by: Jared L <[email protected]> * Update docs/guides/int_basics/modals/intro.md Co-authored-by: Jared L <[email protected]> * Update docs/guides/int_basics/modals/intro.md Co-authored-by: Jared L <[email protected]> * Update docs/guides/int_basics/modals/intro.md Co-authored-by: Jared L <[email protected]> * Update docs/guides/int_basics/modals/intro.md Co-authored-by: Jared L <[email protected]> * Update docs/guides/int_basics/modals/intro.md Co-authored-by: Jared L <[email protected]> * Update docs/guides/int_framework/intro.md Co-authored-by: Jared L <[email protected]> * Update docs/guides/int_framework/intro.md Co-authored-by: Jared L <[email protected]> * Update docs/guides/int_framework/samples/intro/modal.cs Co-authored-by: Jared L <[email protected]> * Update src/Discord.Net.Core/Entities/Interactions/MessageComponents/IComponentInteractionData.cs Co-authored-by: Jared L <[email protected]> * Update src/Discord.Net.Core/Entities/Interactions/MessageComponents/TextInputComponent.cs Co-authored-by: Jared L <[email protected]> * Update src/Discord.Net.Core/Entities/Interactions/Modals/IModalInteraction.cs Co-authored-by: Jared L <[email protected]> * Update src/Discord.Net.Core/Entities/Interactions/Modals/ModalBuilder.cs Co-authored-by: Jared L <[email protected]> * Update src/Discord.Net.Core/Entities/Interactions/Modals/ModalBuilder.cs Co-authored-by: Jared L <[email protected]> * Update src/Discord.Net.Core/Entities/Interactions/Modals/ModalBuilder.cs Co-authored-by: Jared L <[email protected]> * Update src/Discord.Net.Core/Entities/Interactions/Modals/ModalBuilder.cs Co-authored-by: Jared L <[email protected]> * Update src/Discord.Net.Core/Entities/Interactions/Modals/ModalBuilder.cs Co-authored-by: Jared L <[email protected]> * Update src/Discord.Net.Core/Entities/Interactions/Modals/ModalBuilder.cs Co-authored-by: Jared L <[email protected]> * Update src/Discord.Net.Interactions/Attributes/Commands/ModalInteractionAttribute.cs Co-authored-by: Jared L <[email protected]> * Update src/Discord.Net.Interactions/Attributes/Modals/RequiredInputAttribute.cs Co-authored-by: Jared L <[email protected]> * Update src/Discord.Net.Interactions/InteractionServiceConfig.cs Co-authored-by: Jared L <[email protected]> * Update src/Discord.Net.WebSocket/Entities/Interaction/MessageComponents/SocketMessageComponentData.cs Co-authored-by: Jared L <[email protected]> * Update src/Discord.Net.WebSocket/Entities/Interaction/Modals/SocketModalData.cs Co-authored-by: Jared L <[email protected]> * update interaction service modal docs * implements ExitOnMissingmModalField config option and adds Type field to modal info * Add WithValue to text input builders * Fix rare NRE on component enumeration * Fix RequestOptions being required in some methods * Use 'OfType' instead of 'Where' * Remove android unsported warning * Change publicity of properties in IInputComponeontBuilder.cs Co-authored-by: Cenk Ergen <[email protected]> Co-authored-by: Jared L <[email protected]> * Remove complex parameter ref Co-authored-by: CottageDwellingCat <[email protected]> Co-authored-by: Cenk Ergen <[email protected]> Co-authored-by: Jared L <[email protected]>
1 parent 33efd89 commit c8f175e

File tree

80 files changed

+3502
-25
lines changed

Some content is hidden

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

80 files changed

+3502
-25
lines changed

Discord.Net.code-workspace

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,16 +8,16 @@
88
"editor.rulers": [
99
120
1010
],
11+
"editor.insertSpaces": true,
1112
"files.exclude": {
1213
"**/.git": true,
1314
"**/.svn": true,
1415
"**/.hg": true,
1516
"**/CVS": true,
1617
"**/.DS_Store": true,
17-
"docs/": true,
1818
"**/obj": true,
1919
"**/bin": true,
2020
"samples/": true,
2121
}
2222
}
23-
}
23+
}
20.4 KB
Loading
1.76 KB
Loading
10.7 KB
Loading
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
---
2+
uid: Guides.MessageComponents.TextInputs
3+
title: Text Input Components
4+
---
5+
6+
# Text Input Components
7+
8+
> [!WARNING]
9+
> Text input components can only be used in
10+
> [modals](../modals/intro.md).
11+
12+
Text input components are a type of MessageComponents that can only be
13+
used in modals. Texts inputs can be longer (the `Paragraph`) style or
14+
shorter (the `Short` style). Text inputs have a variable min and max
15+
length.
16+
17+
![A modal with short and paragraph text inputs](images/image7.png)
18+
19+
## Creating text inputs
20+
Text input components can be built using the `TextInputBuilder`.
21+
The simplest text input can built with:
22+
```cs
23+
var tb = new TextInputBuilder()
24+
.WithLabel("My Text")
25+
.WithCustomId("text_input");
26+
```
27+
28+
and would produce a component that looks like:
29+
30+
![basic text input component](images/image8.png)
31+
32+
Additional options can be specified to control the placeholder, style,
33+
and min/max length of the input:
34+
```cs
35+
var tb = new TextInputBuilder()
36+
.WithLabel("Labeled")
37+
.WithCustomId("text_input")
38+
.WithStyle(TextInputStyle.Paragraph)
39+
.WithMinLength(6);
40+
.WithMaxLength(42)
41+
.WithRequired(true)
42+
.WithPlaceholder("Consider this place held.");
43+
```
44+
45+
![more advanced text input](images/image9.png)
46+
35.2 KB
Loading
25 KB
Loading
21.9 KB
Loading
23.2 KB
Loading
Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
---
2+
uid: Guides.Modals.Intro
3+
title: Getting Started with Modals
4+
---
5+
# Modals
6+
7+
## Getting started with modals
8+
This guide will show you how to use modals and give a few examples of
9+
valid use cases. If your question is not covered by this guide ask in the
10+
[Discord.Net Discord Server](https://discord.gg/dnet).
11+
12+
### What is a modal?
13+
Modals are forms bots can send when responding to interactions. Modals
14+
are sent to Discord as an array of message components and converted
15+
into the form layout by user's clients. Modals are required to have a
16+
custom id, title, and at least one component.
17+
18+
![Screenshot of a modal](images/image2.png)
19+
20+
When users submit modals, your client fires the ModalSubmitted event.
21+
You can get the components of the modal from the `Data.Components` property
22+
on the SocketModal:
23+
24+
![Screenshot of modal data](images/image1.png)
25+
26+
### Using modals
27+
28+
Lets create a simple modal with an entry field for users to
29+
tell us their favorite food. We can start by creating a slash
30+
command that will respond with the modal.
31+
```cs
32+
[SlashCommand("food", "Tell us about your favorite food!")]
33+
public async Task FoodPreference()
34+
{
35+
// send a modal
36+
}
37+
```
38+
39+
Now that we have our command set up, we need to build a modal.
40+
We can use the aptly named `ModalBuilder` for that:
41+
42+
| Method | Description |
43+
| --------------- | ----------------------------------------- |
44+
| `WithTitle` | Sets the modal's title. |
45+
| `WithCustomId` | Sets the modal's custom id. |
46+
| `AddTextInput` | Adds a `TextInputBuilder` to the modal. |
47+
| `AddComponents` | Adds multiple components to the modal. |
48+
| `Build` | Builds the `ModalBuilder` into a `Modal`. |
49+
50+
We know we need to add a text input to the modal, so let's look at that
51+
method's parameters.
52+
53+
| Parameter | Description |
54+
| ------------- | ------------------------------------------ |
55+
| `label` | Sets the input's label. |
56+
| `customId` | Sets the input's custom id. |
57+
| `style` | Sets the input's style. |
58+
| `placeholder` | Sets the input's placeholder. |
59+
| `minLength` | Sets the minimum input length. |
60+
| `maxLength` | Sets the maximum input length. |
61+
| `required` | Sets whether or not the modal is required. |
62+
| `value` | Sets the input's default value. |
63+
64+
To make a basic text input we would only need to set the `label` and
65+
`customId`, but in this example we will also use the `placeholder`
66+
parameter. Next we can build our modal:
67+
68+
```cs
69+
var mb = new ModalBuilder()
70+
.WithTitle("Fav Food")
71+
.WithCustomId("food_menu")
72+
.AddTextInput("What??", "food_name", placeholder:"Pizza")
73+
.AddTextInput("Why??", "food_reason", TextInputStyle.Paragraph,
74+
"Kus it's so tasty");
75+
```
76+
77+
Now that we have a ModalBuilder we can update our command to respond
78+
with the modal.
79+
80+
```cs
81+
[SlashCommand("food", "Tell us about your favorite food!")]
82+
public async Task FoodPreference()
83+
{
84+
var mb = new ModalBuilder()
85+
.WithTitle("Fav Food")
86+
.WithCustomId("food_menu")
87+
.AddTextInput("What??", "food_name", placeholder:"Pizza")
88+
.AddTextInput("Why??", "food_reason", TextInputStyle.Paragraph,
89+
"Kus it's so tasty");
90+
91+
await Context.Interaction.RespondWithModalAsync(mb.Build());
92+
}
93+
```
94+
95+
When we run the command, our modal should pop up:
96+
97+
![screenshot of the above modal](images/image3.png)
98+
99+
### Respond to modals
100+
101+
> [!WARNING]
102+
> Modals can not be sent when respoding to a modal.
103+
104+
Once a user has submitted the modal, we need to let everyone know what
105+
their favorite food is. We can start by hooking a task to the client's
106+
`ModalSubmitted` event.
107+
```cs
108+
_client.ModalSubmitted += async modal =>
109+
{
110+
// Get the values of components.
111+
List<SocketMessageComponentData> components =
112+
modal.Data.Components.ToList();
113+
string food = components
114+
.Where(x => x.CustomId == "food_name").First().Value;
115+
string reason = components
116+
.Where(x => x.CustomId == "food_reason").First().Value;
117+
118+
// Build the message to send.
119+
string message = "hey @everyone; I just learned " +
120+
$"{modal.User.Mention}'s favorite food is " +
121+
$"{food} because {reason}.";
122+
123+
// Specify the AllowedMentions so we don't actually ping everyone.
124+
AllowedMentions mentions = new AllowedMentions();
125+
mentions.AllowedTypes = AllowedMentionTypes.Users;
126+
127+
// Respond to the modal.
128+
await modal.RespondAsync(message, allowedMentions:mentions);
129+
}
130+
```
131+
132+
Now responding to the modal should inform everyone of our tasty
133+
choices.
134+
135+
![Response of the modal submitted event](images/image4.png)

0 commit comments

Comments
 (0)