Component search fixes & improvements (#3123)
This commit is contained in:
@@ -5,7 +5,7 @@ namespace Discord;
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Represents a <see cref="IMessageComponent"/> Row for child components to live in.
|
/// Represents a <see cref="IMessageComponent"/> Row for child components to live in.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class ActionRowComponent : IMessageComponent
|
public class ActionRowComponent : INestedComponent, IMessageComponent
|
||||||
{
|
{
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public ComponentType Type => ComponentType.ActionRow;
|
public ComponentType Type => ComponentType.ActionRow;
|
||||||
|
|||||||
@@ -341,13 +341,30 @@ public static class ComponentContainerExtensions
|
|||||||
/// </returns>
|
/// </returns>
|
||||||
public static ComponentT FindComponentById<ComponentT>(this IComponentContainer container, int id)
|
public static ComponentT FindComponentById<ComponentT>(this IComponentContainer container, int id)
|
||||||
where ComponentT : class, IMessageComponentBuilder
|
where ComponentT : class, IMessageComponentBuilder
|
||||||
=> container.Components
|
{
|
||||||
.OfType<ComponentT>()
|
if (container is ComponentT cmp && cmp.Id == id)
|
||||||
.FirstOrDefault(x => x.Id == id)
|
return cmp;
|
||||||
?? container.Components
|
|
||||||
.OfType<IComponentContainer>()
|
foreach (var component in container.Components)
|
||||||
.Select(x => x.FindComponentById<ComponentT>(id))
|
{
|
||||||
.FirstOrDefault(x => x is not null);
|
if (component.Id == id && component is ComponentT target)
|
||||||
|
return target;
|
||||||
|
|
||||||
|
if (component is SectionBuilder section
|
||||||
|
&& section.Accessory.Id == id
|
||||||
|
&& section.Accessory is ComponentT targetAccessory)
|
||||||
|
return targetAccessory;
|
||||||
|
|
||||||
|
if (component is IComponentContainer childContainer)
|
||||||
|
{
|
||||||
|
var childSearchResult = childContainer.FindComponentById<ComponentT>(id);
|
||||||
|
if (childSearchResult is not null)
|
||||||
|
return childSearchResult;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets a <see cref="IEnumerable{T}">IEnumerable</see> containing ids of <see cref="IMessageComponentBuilder"/>
|
/// Gets a <see cref="IEnumerable{T}">IEnumerable</see> containing ids of <see cref="IMessageComponentBuilder"/>
|
||||||
@@ -360,4 +377,71 @@ public static class ComponentContainerExtensions
|
|||||||
.Concat(container.Components
|
.Concat(container.Components
|
||||||
.OfType<IComponentContainer>()
|
.OfType<IComponentContainer>()
|
||||||
.SelectMany(x => x.GetComponentIds()));
|
.SelectMany(x => x.GetComponentIds()));
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Finds the first <see cref="IMessageComponent"/> in the <see cref="INestedComponent"/>
|
||||||
|
/// or any of its child <see cref="INestedComponent"/>s with matching id.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>
|
||||||
|
/// The <see cref="IMessageComponent"/> with matching id, <see langword="null"/> otherwise.
|
||||||
|
/// </returns>
|
||||||
|
public static IMessageComponent FindComponentById(this INestedComponent container, int id)
|
||||||
|
=> container.FindComponentById<IMessageComponent>(id);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Finds the first <c>ComponentT</c> in the <see cref="INestedComponent"/>
|
||||||
|
/// or any of its child <see cref="INestedComponent"/>s with matching id.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>
|
||||||
|
/// The <c>ComponentT</c> with matching id, <see langword="null"/> otherwise.
|
||||||
|
/// </returns>
|
||||||
|
public static ComponentT FindComponentById<ComponentT>(this INestedComponent container, int id)
|
||||||
|
where ComponentT : class, IMessageComponent
|
||||||
|
{
|
||||||
|
if (container is ComponentT cmp && cmp.Id == id)
|
||||||
|
return cmp;
|
||||||
|
|
||||||
|
return container.Components.FindComponentById<ComponentT>(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Finds the first <c>ComponentT</c> in the <see cref="IEnumerable{IMessageComponent}"/>
|
||||||
|
/// or any of its child <see cref="INestedComponent"/>s with matching id.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>
|
||||||
|
/// The <c>ComponentT</c> with matching id, <see langword="null"/> otherwise.
|
||||||
|
/// </returns>
|
||||||
|
public static ComponentT FindComponentById<ComponentT>(this IEnumerable<IMessageComponent> components, int id)
|
||||||
|
where ComponentT : class, IMessageComponent
|
||||||
|
{
|
||||||
|
foreach (var component in components)
|
||||||
|
{
|
||||||
|
if (component.Id == id && component is ComponentT target)
|
||||||
|
return target;
|
||||||
|
|
||||||
|
if (component is SectionComponent section
|
||||||
|
&& section.Accessory.Id == id
|
||||||
|
&& section.Accessory is ComponentT targetAccessory)
|
||||||
|
return targetAccessory;
|
||||||
|
|
||||||
|
if (component is INestedComponent childContainer)
|
||||||
|
{
|
||||||
|
var childSearchResult = childContainer.FindComponentById<ComponentT>(id);
|
||||||
|
if (childSearchResult is not null)
|
||||||
|
return childSearchResult;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Finds the first <see cref="IMessageComponent"/> in the <see cref="IEnumerable{IMessageComponent}"/>
|
||||||
|
/// or any of its child <see cref="INestedComponent"/>s with matching id.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>
|
||||||
|
/// The <see cref="IMessageComponent"/> with matching id, <see langword="null"/> otherwise.
|
||||||
|
/// </returns>
|
||||||
|
public static IMessageComponent FindComponentById(this IEnumerable<IMessageComponent> components, int id)
|
||||||
|
=> components.FindComponentById<IMessageComponent>(id);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ namespace Discord;
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Represents a container component.
|
/// Represents a container component.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class ContainerComponent : IMessageComponent
|
public class ContainerComponent : INestedComponent, IMessageComponent
|
||||||
{
|
{
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public ComponentType Type => ComponentType.Container;
|
public ComponentType Type => ComponentType.Container;
|
||||||
|
|||||||
@@ -0,0 +1,14 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace Discord;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Represents a <see cref="IMessageComponent"/> containing child components.
|
||||||
|
/// </summary>
|
||||||
|
public interface INestedComponent
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the child components in this container.
|
||||||
|
/// </summary>
|
||||||
|
IReadOnlyCollection<IMessageComponent> Components { get; }
|
||||||
|
}
|
||||||
@@ -5,7 +5,7 @@ namespace Discord;
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Represents a component object used to send components with messages.
|
/// Represents a component object used to send components with messages.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class MessageComponent
|
public class MessageComponent : INestedComponent
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the components to be used in a message.
|
/// Gets the components to be used in a message.
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ namespace Discord;
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Represents a section component.
|
/// Represents a section component.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class SectionComponent : IMessageComponent
|
public class SectionComponent : INestedComponent, IMessageComponent
|
||||||
{
|
{
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public ComponentType Type => ComponentType.Section;
|
public ComponentType Type => ComponentType.Section;
|
||||||
|
|||||||
Reference in New Issue
Block a user