Skip to content

Commit a476014

Browse files
Misha-133quinchsd4n3436
authored
[Feature] Modal refactoring & select menu support (#3172)
* add missing xmldoc + new component type * add API models * label builder * most POG commit ever * another pog commit (add file upload component) * add a constructor & missing extension methods * refactor modal builder * Fix build errors * Add xml docs and fluent methods to new components * Fix naming * Set default value of `FileUploadComponentBuilder.IsRequired` to `true` * xmldoc fixes * Support receiving modal interactions with new components & implement resolved data * Add missing text display methods to modal builder * Update src/Discord.Net.Rest/API/Common/FileUploadComponent.cs Co-authored-by: Quin Lynch <[email protected]> --------- Co-authored-by: Quin Lynch <[email protected]> Co-authored-by: d4n <[email protected]>
1 parent ca6c9bc commit a476014

34 files changed

+1631
-171
lines changed

src/Discord.Net.Core/Entities/Interactions/MessageComponents/Builders/ButtonBuilder.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ namespace Discord;
99
/// </summary>
1010
public class ButtonBuilder : IInteractableComponentBuilder
1111
{
12+
/// <inheritdoc />
1213
public ComponentType Type => ComponentType.Button;
1314

1415
/// <summary>

src/Discord.Net.Core/Entities/Interactions/MessageComponents/Builders/ComponentBuilder.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ namespace Discord;
1010
public class ComponentBuilder
1111
{
1212
/// <summary>
13-
/// The max length of a <see cref="ButtonComponent.CustomId"/>.
13+
/// The max length of <see cref="ButtonComponent.CustomId"/> and <see cref="SelectMenuComponent.CustomId"/>.
1414
/// </summary>
1515
public const int MaxCustomIdLength = 100;
1616

src/Discord.Net.Core/Entities/Interactions/MessageComponents/Builders/ComponentContainerExtensions.cs

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -469,6 +469,54 @@ public static BuilderT WithActionRow<BuilderT>(this BuilderT container,
469469
return container.WithActionRow(cont);
470470
}
471471

472+
/// <summary>
473+
/// Adds a <see cref="FileUploadComponentBuilder"/> to the container.
474+
/// </summary>
475+
/// <returns>
476+
/// The current container.
477+
/// </returns>
478+
public static BuilderT WithFileUpload<BuilderT>(this BuilderT container, FileUploadComponentBuilder fileUpload)
479+
where BuilderT : class, IInteractableComponentContainer
480+
{
481+
container.AddComponent(fileUpload);
482+
return container;
483+
}
484+
485+
/// <summary>
486+
/// Adds a <see cref="FileUploadComponentBuilder"/> to the container.
487+
/// </summary>
488+
/// <returns>
489+
/// The current container.
490+
/// </returns>
491+
public static BuilderT WithFileUpload<BuilderT>(this BuilderT container,
492+
string customId,
493+
int? minValues = null,
494+
int? maxValues = null,
495+
bool isRequired = true,
496+
int? id = null)
497+
where BuilderT : class, IInteractableComponentContainer
498+
=> container.WithFileUpload(new FileUploadComponentBuilder()
499+
.WithCustomId(customId)
500+
.WithMinValues(minValues)
501+
.WithMaxValues(maxValues)
502+
.WithRequired(isRequired)
503+
.WithId(id));
504+
505+
/// <summary>
506+
/// Adds a <see cref="FileUploadComponentBuilder"/> to the container.
507+
/// </summary>
508+
/// <returns>
509+
/// The current container.
510+
/// </returns>
511+
public static BuilderT WithFileUpload<BuilderT>(this BuilderT container,
512+
Action<FileUploadComponentBuilder> options)
513+
where BuilderT : class, IInteractableComponentContainer
514+
{
515+
var comp = new FileUploadComponentBuilder();
516+
options(comp);
517+
return container.WithFileUpload(comp);
518+
}
519+
472520
/// <summary>
473521
/// Finds the first <see cref="IMessageComponentBuilder"/> in the <see cref="IComponentContainer"/>
474522
/// or any of its child <see cref="IComponentContainer"/>s with matching id.

src/Discord.Net.Core/Entities/Interactions/MessageComponents/Builders/FileComponentBuilder.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@
22

33
namespace Discord;
44

5+
/// <summary>
6+
/// Represents a class used to build <see cref="FileComponent"/>'s.
7+
/// </summary>
58
public class FileComponentBuilder : IMessageComponentBuilder
69
{
710
/// <inheritdoc />
Lines changed: 192 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,192 @@
1+
using System;
2+
3+
namespace Discord;
4+
5+
/// <summary>
6+
/// Represents a class used to build <see cref="FileUploadComponent"/>'s.
7+
/// </summary>
8+
public class FileUploadComponentBuilder : IInteractableComponentBuilder
9+
{
10+
/// <summary>
11+
/// The maximum number of values for the <see cref="FileUploadComponentBuilder.MinValues"/> and <see cref="FileUploadComponentBuilder.MaxValues"/> properties.
12+
/// </summary>
13+
public const int MaxFileCount = 10;
14+
15+
/// <inheritdoc/>
16+
public ComponentType Type => ComponentType.FileUpload;
17+
18+
/// <inheritdoc />
19+
public int? Id { get; set; }
20+
21+
/// <summary>
22+
/// Gets or sets the custom id of the current file upload.
23+
/// </summary>
24+
/// <exception cref="ArgumentException" accessor="set"><see cref="CustomId"/> length exceeds <see cref="ModalComponentBuilder.MaxCustomIdLength"/>.</exception>
25+
/// <exception cref="ArgumentException" accessor="set"><see cref="CustomId"/> length subceeds 1.</exception>
26+
public string CustomId
27+
{
28+
get => _customId;
29+
set
30+
{
31+
if (value is not null)
32+
{
33+
Preconditions.AtLeast(value.Length, 1, nameof(CustomId));
34+
Preconditions.AtMost(value.Length, ModalComponentBuilder.MaxCustomIdLength, nameof(CustomId));
35+
}
36+
37+
_customId = value;
38+
}
39+
}
40+
41+
/// <summary>
42+
/// Gets or sets the minimum number of items that must be uploaded (defaults to 1).
43+
/// </summary>
44+
/// <exception cref="ArgumentException" accessor="set"><see cref="MinValues"/> exceeds <see cref="MaxFileCount"/>.</exception>
45+
/// <exception cref="ArgumentException" accessor="set"><see cref="MinValues"/> length subceeds 0.</exception>
46+
public int? MinValues
47+
{
48+
get => _minValues;
49+
set
50+
{
51+
if (value is not null)
52+
{
53+
Preconditions.AtLeast(value.Value, 0, nameof(MinValues));
54+
Preconditions.AtMost(value.Value, MaxFileCount, nameof(MinValues));
55+
}
56+
57+
_minValues = value;
58+
}
59+
}
60+
61+
/// <summary>
62+
/// Gets or sets the maximum number of items that can be uploaded (defaults to 1).
63+
/// </summary>
64+
/// <exception cref="ArgumentException" accessor="set"><see cref="MaxValues"/> exceeds <see cref="MaxFileCount"/>.</exception>
65+
public int? MaxValues
66+
{
67+
get => _maxValues;
68+
set
69+
{
70+
if (value is not null)
71+
{
72+
Preconditions.AtMost(value.Value, MaxFileCount, nameof(MaxValues));
73+
}
74+
75+
_maxValues = value;
76+
}
77+
}
78+
79+
/// <summary>
80+
/// Gets or sets a value indicating whether the current file upload requires files to be uploaded before submitting the modal (defaults to <see langword="true"></see>).
81+
/// </summary>
82+
public bool IsRequired { get; set; } = true;
83+
84+
/// <summary>
85+
/// Sets the custom id of the current file upload.
86+
/// </summary>
87+
/// <param name="customId">The id to use for the current file upload.</param>
88+
/// <inheritdoc cref="CustomId"/>
89+
/// <returns>The current builder.</returns>
90+
public FileUploadComponentBuilder WithCustomId(string customId)
91+
{
92+
CustomId = customId;
93+
return this;
94+
}
95+
96+
/// <summary>
97+
/// Sets the minimum number of items that must be uploaded (defaults to 1).
98+
/// </summary>
99+
/// <param name="minValues">Sets the minimum number of items that must be uploaded.</param>
100+
/// <inheritdoc cref="MinValues"/>
101+
/// <returns>
102+
/// The current builder.
103+
/// </returns>
104+
public FileUploadComponentBuilder WithMinValues(int? minValues)
105+
{
106+
MinValues = minValues;
107+
return this;
108+
}
109+
110+
/// <summary>
111+
/// Sets the maximum number of items that can be uploaded (defaults to 1).
112+
/// </summary>
113+
/// <param name="maxValues">The maximum number of items that can be uploaded.</param>
114+
/// <inheritdoc cref="MaxValues"/>
115+
/// <returns>
116+
/// The current builder.
117+
/// </returns>
118+
public FileUploadComponentBuilder WithMaxValues(int? maxValues)
119+
{
120+
MaxValues = maxValues;
121+
return this;
122+
}
123+
124+
/// <summary>
125+
/// Sets whether the current file upload requires files to be uploaded before submitting the modal.
126+
/// </summary>
127+
/// <param name="isRequired">Whether the current file upload requires files to be uploaded before submitting the modal.</param>
128+
/// <returns>
129+
/// The current builder.
130+
/// </returns>
131+
public FileUploadComponentBuilder WithRequired(bool isRequired)
132+
{
133+
IsRequired = isRequired;
134+
return this;
135+
}
136+
137+
private string _customId;
138+
private int? _minValues;
139+
private int? _maxValues;
140+
141+
/// <summary>
142+
/// Initializes a new instance of the <see cref="FileUploadComponentBuilder"/>.
143+
/// </summary>
144+
public FileUploadComponentBuilder() {}
145+
146+
/// <summary>
147+
/// Initializes a new instance of the <see cref="FileUploadComponentBuilder"/>.
148+
/// </summary>
149+
/// <param name="customId">The custom id of the current file upload.</param>
150+
/// <param name="minValues">The minimum number of items that must be uploaded (defaults to 1).</param>
151+
/// <param name="maxValues">the maximum number of items that can be uploaded (defaults to 1).</param>
152+
/// <param name="isRequired">Whether the current file upload requires files to be uploaded before submitting the modal.</param>
153+
/// <param name="id">The id for the component.</param>
154+
public FileUploadComponentBuilder(string customId, int? minValues = null, int? maxValues = null, bool isRequired = true, int? id = null)
155+
{
156+
CustomId = customId;
157+
MinValues = minValues;
158+
MaxValues = maxValues;
159+
IsRequired = isRequired;
160+
Id = id;
161+
}
162+
163+
/// <summary>
164+
/// Initializes a new instance of the <see cref="FileUploadComponentBuilder"/> class from an existing <see cref="FileUploadComponent"/>.
165+
/// </summary>
166+
/// <param name="fileUpload">The component.</param>
167+
public FileUploadComponentBuilder(FileUploadComponent fileUpload)
168+
{
169+
CustomId = fileUpload.CustomId;
170+
MinValues = fileUpload.MinValues;
171+
MaxValues = fileUpload.MaxValues;
172+
IsRequired = fileUpload.IsRequired;
173+
Id = fileUpload.Id;
174+
}
175+
176+
/// <inheritdoc cref="IMessageComponentBuilder.Build" />
177+
public FileUploadComponent Build()
178+
{
179+
Preconditions.NotNullOrWhitespace(CustomId, nameof(CustomId));
180+
181+
if (MinValues is not null && MaxValues is not null)
182+
Preconditions.AtLeast(MaxValues.Value, MinValues.Value, nameof(MaxValues));
183+
184+
Preconditions.AtMost(MinValues ?? 0, MaxFileCount, nameof(MinValues));
185+
Preconditions.AtMost(MaxValues ?? 0, MaxFileCount, nameof(MaxValues));
186+
187+
return new FileUploadComponent(Id, CustomId, MinValues, MaxValues, IsRequired);
188+
}
189+
190+
/// <inheritdoc/>
191+
IMessageComponent IMessageComponentBuilder.Build() => Build();
192+
}

0 commit comments

Comments
 (0)