Skip to content

Commit c4299db

Browse files
Implement RadioGroup, CheckboxGroup, and Checkbox modal components (#138)
* Implement new modal components: RadioGroup, CheckboxGroup, Checkbox This commit introduces support for the new Discord components: Radio Group, Checkbox Group, and Checkbox. Key changes: - Added `ComponentType` enum values for `RadioGroup`, `CheckboxGroup`, and `Checkbox`. - Created JSON models for local and modal (transient) representations of these components. - Implemented `LocalComponent` classes (`LocalRadioGroupComponent`, `LocalCheckboxGroupComponent`, `LocalCheckboxComponent`) for constructing these components. - Implemented `IModalComponent` interfaces and `TransientModalComponent` classes for handling received components in modal submissions. - Updated `LocalComponent.ToModel()` to serialize the new components properly. - Updated `BindValues` command execution step to support parameter binding for these new component types in modal commands. Co-authored-by: Quahu <24848652+Quahu@users.noreply.github.com> * Implement new modal components: RadioGroup, CheckboxGroup, Checkbox This commit introduces support for the new Discord components: Radio Group, Checkbox Group, and Checkbox. Key changes: - Added `ComponentType` enum values for `RadioGroup`, `CheckboxGroup`, and `Checkbox`. - Created JSON models for local and modal (transient) representations of these components. - Implemented `LocalComponent` classes (`LocalRadioGroupComponent`, `LocalCheckboxGroupComponent`, `LocalCheckboxComponent`) for constructing these components. - Implemented `IModalComponent` interfaces and `TransientModalComponent` classes for handling received components in modal submissions. - Updated `LocalComponent.ToModel()` to serialize the new components properly. - Updated `BindValues` command execution step to support parameter binding for these new component types in modal commands. - Added fluent builder extension methods for the new local components. Co-authored-by: Quahu <24848652+Quahu@users.noreply.github.com> * Implement new modal components: RadioGroup, CheckboxGroup, Checkbox This commit introduces support for the new Discord components: Radio Group, Checkbox Group, and Checkbox. Key changes: - Added `ComponentType` enum values for `RadioGroup`, `CheckboxGroup`, and `Checkbox`. - Created JSON models for local and modal (transient) representations of these components. - Implemented `LocalComponent` classes (`LocalRadioGroupComponent`, `LocalCheckboxGroupComponent`, `LocalCheckboxComponent`) for constructing these components. - Implemented `IModalComponent` interfaces and `TransientModalComponent` classes for handling received components in modal submissions. - Updated `LocalComponent.ToModel()` to serialize the new components properly. - Updated `BindValues` command execution step to support parameter binding for these new component types in modal commands. - Added fluent builder extension methods for the new local components. - Ensured consistency with existing component patterns, including usage of `Optional<T>` and generic extension methods. Co-authored-by: Quahu <24848652+Quahu@users.noreply.github.com> * Implement new modal components: RadioGroup, CheckboxGroup, Checkbox This commit introduces full support for the new Discord modal components: Radio Group, Checkbox Group, and Checkbox. Key changes: - Added `ComponentType` enum values for `RadioGroup`, `CheckboxGroup`, and `Checkbox`. - Created JSON models for local and modal (transient) representations of these components. - Implemented `LocalComponent` classes (`LocalRadioGroupComponent`, `LocalCheckboxGroupComponent`, `LocalCheckboxComponent`) and their option classes. - Implemented `IModalComponent` interfaces and `TransientModalComponent` classes. - Updated `LocalComponent.ToModel()` to serialize the new components properly, using `OptionalGuard` for validation. - Updated `ModalComponentConverter` to handle polymorphic deserialization of the new component types. - Updated `BindValues` command execution step to support parameter binding for these new component types in modal commands. - Added fluent builder extension methods and static factory methods (`LocalComponent.RadioGroup`, etc.). - Ensured correct use of `Optional<IList<T>>` for option lists and removed unsupported `Emoji` properties from options. Co-authored-by: Quahu <24848652+Quahu@users.noreply.github.com> * Implement new modal components: RadioGroup, CheckboxGroup, Checkbox This commit fully implements support for the new Discord modal components: Radio Group, Checkbox Group, and Checkbox. Key changes: - Added `ComponentType` enum values for `RadioGroup`, `CheckboxGroup`, and `Checkbox`. - Created JSON models for local and modal (transient) representations of these components. - Implemented `LocalComponent` classes (`LocalRadioGroupComponent`, `LocalCheckboxGroupComponent`, `LocalCheckboxComponent`) and their option classes. - Implemented `IModalComponent` interfaces and `TransientModalComponent` classes for receiving modal submissions. - Updated `LocalComponent.ToModel()` to serialize the new components properly, using `OptionalGuard` for validation. - Updated `ModalComponentConverter` to handle polymorphic deserialization of the new component types. - Updated `BindValues` command execution step to support parameter binding for these new component types in modal commands. - Added fluent builder extension methods and static factory methods (`LocalComponent.RadioGroup`, etc.). - Ensured correct use of `Optional<IList<T>>` for option lists and removed unsupported `Emoji` properties from options. - Added `Label` support for Checkbox (optional). Co-authored-by: Quahu <24848652+Quahu@users.noreply.github.com> * Remove label from Checkbox factory method --------- Co-authored-by: google-labs-jules[bot] <161369871+google-labs-jules[bot]@users.noreply.github.com>
1 parent e20e7ce commit c4299db

30 files changed

+1034
-296
lines changed

src/Disqord.Bot/Commands/Implementation/Components/ExecutionSteps/BindValues.cs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,20 @@ protected virtual MultiString GetRawArgumentFromModalComponent(IModalComponent m
190190
{
191191
return ToMultiString(fileUploadComponent.AttachmentIds.Select(static id => id.ToString()));
192192
}
193+
case IModalRadioGroupComponent radioGroupComponent:
194+
{
195+
return radioGroupComponent.Value != null
196+
? new MultiString(radioGroupComponent.Value)
197+
: default;
198+
}
199+
case IModalCheckboxGroupComponent checkboxGroupComponent:
200+
{
201+
return ToMultiString(checkboxGroupComponent.Values);
202+
}
203+
case IModalCheckboxComponent checkboxComponent:
204+
{
205+
return new MultiString(checkboxComponent.Value.ToString());
206+
}
193207
default:
194208
{
195209
ThrowNotImplementedException($"{nameof(BindValues)}.{nameof(GetRawArgumentFromModalComponent)}() does not support the modal component of type: {modalComponent.Type} (ID: {modalComponent.Id}).");
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
namespace Disqord;
2+
3+
public interface IModalCheckboxComponent : IModalComponent, ICustomIdentifiableEntity
4+
{
5+
bool Value { get; }
6+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
using System.Collections.Generic;
2+
3+
namespace Disqord;
4+
5+
public interface IModalCheckboxGroupComponent : IModalComponent, ICustomIdentifiableEntity
6+
{
7+
IReadOnlyList<string> Values { get; }
8+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
namespace Disqord;
2+
3+
public interface IModalRadioGroupComponent : IModalComponent, ICustomIdentifiableEntity
4+
{
5+
string? Value { get; }
6+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
namespace Disqord;
2+
3+
public static class LocalCheckboxComponentExtensions
4+
{
5+
public static TCheckboxComponent WithLabel<TCheckboxComponent>(this TCheckboxComponent checkboxComponent, string label)
6+
where TCheckboxComponent : LocalCheckboxComponent
7+
{
8+
checkboxComponent.Label = label;
9+
return checkboxComponent;
10+
}
11+
12+
public static TCheckboxComponent WithIsDefault<TCheckboxComponent>(this TCheckboxComponent checkboxComponent, bool isDefault = true)
13+
where TCheckboxComponent : LocalCheckboxComponent
14+
{
15+
checkboxComponent.IsDefault = isDefault;
16+
return checkboxComponent;
17+
}
18+
19+
public static TCheckboxComponent WithIsDisabled<TCheckboxComponent>(this TCheckboxComponent checkboxComponent, bool isDisabled = true)
20+
where TCheckboxComponent : LocalCheckboxComponent
21+
{
22+
checkboxComponent.IsDisabled = isDisabled;
23+
return checkboxComponent;
24+
}
25+
}
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
using System.Collections.Generic;
2+
using Qommon;
3+
4+
namespace Disqord;
5+
6+
public static class LocalCheckboxGroupComponentExtensions
7+
{
8+
public static TCheckboxGroupComponent AddOption<TCheckboxGroupComponent>(this TCheckboxGroupComponent component, string label, string value, string? description = null, bool isDefault = false)
9+
where TCheckboxGroupComponent : LocalCheckboxGroupComponent
10+
{
11+
var option = new LocalCheckboxGroupOption(label, value)
12+
{
13+
IsDefault = isDefault
14+
};
15+
16+
if (description != null)
17+
option.Description = description;
18+
19+
return component.AddOption(option);
20+
}
21+
22+
public static TCheckboxGroupComponent AddOption<TCheckboxGroupComponent>(this TCheckboxGroupComponent component, LocalCheckboxGroupOption option)
23+
where TCheckboxGroupComponent : LocalCheckboxGroupComponent
24+
{
25+
if (component.Options.Add(option, out var list))
26+
component.Options = new(list);
27+
28+
return component;
29+
}
30+
31+
public static TCheckboxGroupComponent WithOptions<TCheckboxGroupComponent>(this TCheckboxGroupComponent component, IEnumerable<LocalCheckboxGroupOption> options)
32+
where TCheckboxGroupComponent : LocalCheckboxGroupComponent
33+
{
34+
Guard.IsNotNull(options);
35+
36+
if (component.Options.With(options, out var list))
37+
component.Options = new(list);
38+
39+
return component;
40+
}
41+
42+
public static TCheckboxGroupComponent WithOptions<TCheckboxGroupComponent>(this TCheckboxGroupComponent component, params LocalCheckboxGroupOption[] options)
43+
where TCheckboxGroupComponent : LocalCheckboxGroupComponent
44+
=> component.WithOptions((IEnumerable<LocalCheckboxGroupOption>) options);
45+
46+
public static TCheckboxGroupComponent WithMinimumSelectedOptions<TCheckboxGroupComponent>(this TCheckboxGroupComponent checkboxGroupComponent, int minimumSelectedOptions)
47+
where TCheckboxGroupComponent : LocalCheckboxGroupComponent
48+
{
49+
checkboxGroupComponent.MinimumSelectedOptions = minimumSelectedOptions;
50+
return checkboxGroupComponent;
51+
}
52+
53+
public static TCheckboxGroupComponent WithMaximumSelectedOptions<TCheckboxGroupComponent>(this TCheckboxGroupComponent checkboxGroupComponent, int maximumSelectedOptions)
54+
where TCheckboxGroupComponent : LocalCheckboxGroupComponent
55+
{
56+
checkboxGroupComponent.MaximumSelectedOptions = maximumSelectedOptions;
57+
return checkboxGroupComponent;
58+
}
59+
60+
public static TCheckboxGroupComponent WithIsRequired<TCheckboxGroupComponent>(this TCheckboxGroupComponent checkboxGroupComponent, bool isRequired = true)
61+
where TCheckboxGroupComponent : LocalCheckboxGroupComponent
62+
{
63+
checkboxGroupComponent.IsRequired = isRequired;
64+
return checkboxGroupComponent;
65+
}
66+
67+
public static TCheckboxGroupComponent WithIsDisabled<TCheckboxGroupComponent>(this TCheckboxGroupComponent checkboxGroupComponent, bool isDisabled = true)
68+
where TCheckboxGroupComponent : LocalCheckboxGroupComponent
69+
{
70+
checkboxGroupComponent.IsDisabled = isDisabled;
71+
return checkboxGroupComponent;
72+
}
73+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
using Qommon;
2+
3+
namespace Disqord;
4+
5+
public static class LocalCheckboxGroupOptionExtensions
6+
{
7+
public static LocalCheckboxGroupOption WithLabel(this LocalCheckboxGroupOption option, string label)
8+
{
9+
option.Label = label;
10+
return option;
11+
}
12+
13+
public static LocalCheckboxGroupOption WithValue(this LocalCheckboxGroupOption option, string value)
14+
{
15+
option.Value = value;
16+
return option;
17+
}
18+
19+
public static LocalCheckboxGroupOption WithDescription(this LocalCheckboxGroupOption option, string description)
20+
{
21+
option.Description = description;
22+
return option;
23+
}
24+
25+
public static LocalCheckboxGroupOption WithIsDefault(this LocalCheckboxGroupOption option, bool isDefault = true)
26+
{
27+
option.IsDefault = isDefault;
28+
return option;
29+
}
30+
}
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
using System.Collections.Generic;
2+
using Qommon;
3+
4+
namespace Disqord;
5+
6+
public static class LocalRadioGroupComponentExtensions
7+
{
8+
public static TRadioGroupComponent AddOption<TRadioGroupComponent>(this TRadioGroupComponent component, string label, string value, string? description = null, bool isDefault = false)
9+
where TRadioGroupComponent : LocalRadioGroupComponent
10+
{
11+
var option = new LocalRadioGroupOption(label, value)
12+
{
13+
IsDefault = isDefault
14+
};
15+
16+
if (description != null)
17+
option.Description = description;
18+
19+
return component.AddOption(option);
20+
}
21+
22+
public static TRadioGroupComponent AddOption<TRadioGroupComponent>(this TRadioGroupComponent component, LocalRadioGroupOption option)
23+
where TRadioGroupComponent : LocalRadioGroupComponent
24+
{
25+
if (component.Options.Add(option, out var list))
26+
component.Options = new(list);
27+
28+
return component;
29+
}
30+
31+
public static TRadioGroupComponent WithOptions<TRadioGroupComponent>(this TRadioGroupComponent component, IEnumerable<LocalRadioGroupOption> options)
32+
where TRadioGroupComponent : LocalRadioGroupComponent
33+
{
34+
Guard.IsNotNull(options);
35+
36+
if (component.Options.With(options, out var list))
37+
component.Options = new(list);
38+
39+
return component;
40+
}
41+
42+
public static TRadioGroupComponent WithOptions<TRadioGroupComponent>(this TRadioGroupComponent component, params LocalRadioGroupOption[] options)
43+
where TRadioGroupComponent : LocalRadioGroupComponent
44+
=> component.WithOptions((IEnumerable<LocalRadioGroupOption>) options);
45+
46+
public static TRadioGroupComponent WithIsRequired<TRadioGroupComponent>(this TRadioGroupComponent radioGroupComponent, bool isRequired = true)
47+
where TRadioGroupComponent : LocalRadioGroupComponent
48+
{
49+
radioGroupComponent.IsRequired = isRequired;
50+
return radioGroupComponent;
51+
}
52+
53+
public static TRadioGroupComponent WithIsDisabled<TRadioGroupComponent>(this TRadioGroupComponent radioGroupComponent, bool isDisabled = true)
54+
where TRadioGroupComponent : LocalRadioGroupComponent
55+
{
56+
radioGroupComponent.IsDisabled = isDisabled;
57+
return radioGroupComponent;
58+
}
59+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
using Qommon;
2+
3+
namespace Disqord;
4+
5+
public static class LocalRadioGroupOptionExtensions
6+
{
7+
public static LocalRadioGroupOption WithLabel(this LocalRadioGroupOption option, string label)
8+
{
9+
option.Label = label;
10+
return option;
11+
}
12+
13+
public static LocalRadioGroupOption WithValue(this LocalRadioGroupOption option, string value)
14+
{
15+
option.Value = value;
16+
return option;
17+
}
18+
19+
public static LocalRadioGroupOption WithDescription(this LocalRadioGroupOption option, string description)
20+
{
21+
option.Description = description;
22+
return option;
23+
}
24+
25+
public static LocalRadioGroupOption WithIsDefault(this LocalRadioGroupOption option, bool isDefault = true)
26+
{
27+
option.IsDefault = isDefault;
28+
return option;
29+
}
30+
}

src/Disqord.Core/Entities/Local/Interaction/Components/LocalComponent.Construction.cs

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
using System;
1+
using System;
22
using System.Collections.Generic;
33

44
namespace Disqord;
@@ -160,4 +160,24 @@ public static LocalFileUploadComponent FileUpload(string customId)
160160
return new LocalFileUploadComponent()
161161
.WithCustomId(customId);
162162
}
163+
164+
public static LocalRadioGroupComponent RadioGroup(string customId, params IEnumerable<LocalRadioGroupOption> options)
165+
{
166+
return new LocalRadioGroupComponent()
167+
.WithCustomId(customId)
168+
.WithOptions(options);
169+
}
170+
171+
public static LocalCheckboxGroupComponent CheckboxGroup(string customId, params IEnumerable<LocalCheckboxGroupOption> options)
172+
{
173+
return new LocalCheckboxGroupComponent()
174+
.WithCustomId(customId)
175+
.WithOptions(options);
176+
}
177+
178+
public static LocalCheckboxComponent Checkbox(string customId)
179+
{
180+
return new LocalCheckboxComponent()
181+
.WithCustomId(customId);
182+
}
163183
}

0 commit comments

Comments
 (0)