@@ -2,15 +2,31 @@ using Discord.Interactions.Builders;
using System;
using System;
using System.Collections.Concurrent;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Collections.Generic;
using System.Threading.Tasks;
namespace Discord.Interactions
namespace Discord.Interactions
{
{
internal static class ModalUtils
/// <summary>
/// General utility class regarding <see cref="IModal"/> implementations.
/// </summary>
public static class ModalUtils
{
{
private static readonly ConcurrentDictionary<Type, ModalInfo> _modalInfos = new();
private static readonly ConcurrentDictionary<Type, ModalInfo> _modalInfos = new();
/// <summary>
/// Get a collection of built <see cref="ModalInfo"/> object of cached <see cref="IModal"/> implementatios.
/// </summary>
public static IReadOnlyCollection<ModalInfo> Modals => _modalInfos.Values.ToReadOnlyCollection();
public static IReadOnlyCollection<ModalInfo> Modals => _modalInfos.Values.ToReadOnlyCollection();
/// <summary>
/// Get or add a <see cref="ModalInfo"/> to the shared cache.
/// </summary>
/// <param name="type">Type of the <see cref="IModal"/> implementation.</param>
/// <param name="interactionService">Instance of <see cref="InteractionService"/> in use.</param>
/// <returns>
/// The built instance of <see cref="ModalInfo"/>.
/// </returns>
/// <exception cref="ArgumentException">Thrown when <paramref name="type"/> isn't an implementation of <see cref="IModal"/>.</exception>
public static ModalInfo GetOrAdd(Type type, InteractionService interactionService)
public static ModalInfo GetOrAdd(Type type, InteractionService interactionService)
{
{
if (!typeof(IModal).IsAssignableFrom(type))
if (!typeof(IModal).IsAssignableFrom(type))
@@ -19,9 +35,26 @@ namespace Discord.Interactions
return _modalInfos.GetOrAdd(type, ModuleClassBuilder.BuildModalInfo(type, interactionService));
return _modalInfos.GetOrAdd(type, ModuleClassBuilder.BuildModalInfo(type, interactionService));
}
}
/// <summary>
/// Get or add a <see cref="ModalInfo"/> to the shared cache.
/// </summary>
/// <typeparam name="T">Type of the <see cref="IModal"/> implementation.</typeparam>
/// <param name="interactionService">Instance of <see cref="InteractionService"/> in use.</param>
/// <returns>
/// The built instance of <see cref="ModalInfo"/>.
/// </returns>
public static ModalInfo GetOrAdd<T>(InteractionService interactionService) where T : class, IModal
public static ModalInfo GetOrAdd<T>(InteractionService interactionService) where T : class, IModal
=> GetOrAdd(typeof(T), interactionService);
=> GetOrAdd(typeof(T), interactionService);
/// <summary>
/// Gets the <see cref="ModalInfo"/> associated with an <see cref="IModal"/> implementation.
/// </summary>
/// <param name="type">Type of the <see cref="IModal"/> implementation.</param>
/// <param name="modalInfo">The built instance of <see cref="ModalInfo"/>.</param>
/// <returns>
/// A bool representing whether the fetch operation was successful.
/// </returns>
/// <exception cref="ArgumentException">Thrown when <paramref name="type"/> isn't an implementation of <see cref="IModal"/>.</exception>
public static bool TryGet(Type type, out ModalInfo modalInfo)
public static bool TryGet(Type type, out ModalInfo modalInfo)
{
{
if (!typeof(IModal).IsAssignableFrom(type))
if (!typeof(IModal).IsAssignableFrom(type))
@@ -30,9 +63,26 @@ namespace Discord.Interactions
return _modalInfos.TryGetValue(type, out modalInfo);
return _modalInfos.TryGetValue(type, out modalInfo);
}
}
/// <summary>
/// Gets the <see cref="ModalInfo"/> associated with an <see cref="IModal"/> implementation.
/// </summary>
/// <typeparam name="T">Type of the <see cref="IModal"/> implementation.</typeparam>
/// <param name="modalInfo">The built instance of <see cref="ModalInfo"/>.</param>
/// <returns>
/// A bool representing whether the fetch operation was successful.
/// </returns>
public static bool TryGet<T>(out ModalInfo modalInfo) where T : class, IModal
public static bool TryGet<T>(out ModalInfo modalInfo) where T : class, IModal
=> TryGet(typeof(T), out modalInfo);
=> TryGet(typeof(T), out modalInfo);
/// <summary>
/// Remove the <see cref="ModalInfo"/> entry from the cache associated with an <see cref="IModal"/> implementation.
/// </summary>
/// <param name="type">Type of the <see cref="IModal"/> implementation.</param>
/// <param name="modalInfo">The instance of the removed <see cref="ModalInfo"/> entry.</param>
/// <returns>
/// A bool representing whether the removal operation was successful.
/// </returns>
/// <exception cref="ArgumentException">Thrown when <paramref name="type"/> isn't an implementation of <see cref="IModal"/>.</exception>
public static bool TryRemove(Type type, out ModalInfo modalInfo)
public static bool TryRemove(Type type, out ModalInfo modalInfo)
{
{
if (!typeof(IModal).IsAssignableFrom(type))
if (!typeof(IModal).IsAssignableFrom(type))
@@ -41,11 +91,49 @@ namespace Discord.Interactions
return _modalInfos.TryRemove(type, out modalInfo);
return _modalInfos.TryRemove(type, out modalInfo);
}
}
/// <summary>
/// Remove the <see cref="ModalInfo"/> entry from the cache associated with an <see cref="IModal"/> implementation.
/// </summary>
/// <typeparam name="T">Type of the <see cref="IModal"/> implementation.</typeparam>
/// <param name="modalInfo">The instance of the removed <see cref="ModalInfo"/> entry.</param>
/// <returns>
/// A bool representing whether the removal operation was successful.
/// </returns>
public static bool TryRemove<T>(out ModalInfo modalInfo) where T : class, IModal
public static bool TryRemove<T>(out ModalInfo modalInfo) where T : class, IModal
=> TryRemove(typeof(T), out modalInfo);
=> TryRemove(typeof(T), out modalInfo);
/// <summary>
/// Initialize an <see cref="IModal"/> implementation from a <see cref="IModalInteraction"/> based <see cref="IInteractionContext"/>.
/// </summary>
/// <typeparam name="TModal">Type of the <see cref="IModal"/> implementation.</typeparam>
/// <param name="context">Context of the <see cref="IModalInteraction"/>.</param>
/// <param name="services">Service provider to be passed on to the <see cref="ComponentTypeConverter"/>s.</param>
/// <returns>
/// A Task representing the asyncronous <see cref="IModal"/> initialization operation with a <typeparamref name="TModal"/> result,
/// the result is <see langword="null"/> if the process was unsuccessful.
/// </returns>
public static async Task<TModal> CreateModalAsync<TModal>(IInteractionContext context, IServiceProvider services = null)
where TModal : class, IModal
{
if (!TryGet<TModal>(out var modalInfo))
return null;
var result = await modalInfo.CreateModalAsync(context, services, true).ConfigureAwait(false);
if (!result.IsSuccess || result is not ParseResult parseResult)
return null;
return parseResult.Value as TModal;
}
/// <summary>
/// Clears the <see cref="ModalInfo"/> cache.
/// </summary>
public static void Clear() => _modalInfos.Clear();
public static void Clear() => _modalInfos.Clear();
public static int Count() => _modalInfos.Count;
/// <summary>
/// Gets the count <see cref="ModalInfo"/> entries in the cache.
/// </summary>
public static int Count => _modalInfos.Count;
}
}
}
}