Docs/components v2 :wires: (#3162)
* new pages :3 * fimished intro page * fimished interaction page * remove unused shit * I think we are done lmao * I lied, fixed some small mistakes * Update docs/guides/components_v2/interaction.md Co-authored-by: Mihail Gribkov <61027276+Misha-133@users.noreply.github.com> * misha quality assurance :3 + breakings pages * Apply suggestions from code review Co-authored-by: Mihail Gribkov <61027276+Misha-133@users.noreply.github.com> * component types guide expanded * :3 * Apply suggestions from code review Co-authored-by: Mihail Gribkov <61027276+Misha-133@users.noreply.github.com> --------- Co-authored-by: Mihail Gribkov <61027276+Misha-133@users.noreply.github.com>
This commit is contained in:
57
docs/guides/components_v2/samples/component.cs
Normal file
57
docs/guides/components_v2/samples/component.cs
Normal file
@@ -0,0 +1,57 @@
|
||||
private static ComponentBuilderV2 BuildComponentUnsafe(Recipe recipe, Units units = Units.Si)
|
||||
{
|
||||
StringBuilder ingredients = new($"## Ingredients{Environment.NewLine}");
|
||||
StringBuilder instructions = new($"## Instructions{Environment.NewLine}");
|
||||
ButtonBuilder servingsModalButton = new ButtonBuilder()
|
||||
.WithCustomId(RecipeServingsModal)
|
||||
.WithLabel("Set servings")
|
||||
.WithStyle(ButtonStyle.Primary);
|
||||
|
||||
foreach (RecipeIngredient recipeIngredient in recipe.RecipeIngredients)
|
||||
{
|
||||
ingredients.Append($"`{recipeIngredient.Quantity} {recipeIngredient.Unit.ToSymbol()}` {recipeIngredient.Ingredient.Name} ");
|
||||
|
||||
if (recipeIngredient.Optional)
|
||||
ingredients.AppendLine("[Optional]");
|
||||
else
|
||||
ingredients.Append(Environment.NewLine);
|
||||
}
|
||||
|
||||
for (var i = 0; i < recipe.Instruction.Length; i++)
|
||||
instructions.AppendLine($"`{i + 1}.` {recipe.Instruction[i]}{Environment.NewLine}");
|
||||
|
||||
return new ComponentBuilderV2()
|
||||
.WithTextDisplay($"# {recipe.Name}", RecipeNameDisplay)
|
||||
.WithTextDisplay($"-# {recipe.Servings} servings", RecipeServingsDisplay)
|
||||
.WithMediaGallery([
|
||||
"https://cdn.discordapp.com/attachments/964253122547552349/1336440069892083712/7Q3S.gif?ex=67a3d04e&is=67a27ece&hm=059c9d28466f43a50c4b450ca26fc01298a2080356421d8524384bf67ea8f3ab&"
|
||||
])
|
||||
.WithActionRow([servingsModalButton])
|
||||
.WithTextDisplay(ingredients.ToString())
|
||||
.WithTextDisplay($"""
|
||||
## Oven Settings
|
||||
Mode: `{recipe.OvenMode.ToHumanReadable()}`
|
||||
Temperature: `{recipe.Temperature.Convert(Unit.Temperature, Units.Si, units)} {units.ToSymbol()}`
|
||||
""")
|
||||
.WithActionRow([
|
||||
new SelectMenuBuilder(
|
||||
RecipeUnitInput,
|
||||
options:[
|
||||
new SelectMenuOptionBuilder(
|
||||
"Metric",
|
||||
"1",
|
||||
isDefault: units == Units.Metric),
|
||||
new SelectMenuOptionBuilder(
|
||||
"Imperial",
|
||||
"2",
|
||||
isDefault: units == Units.Imperial),
|
||||
new SelectMenuOptionBuilder(
|
||||
"Kelvin",
|
||||
"0",
|
||||
isDefault: units == Units.Si)
|
||||
],
|
||||
id: RecipeUnitSelectMenu
|
||||
)
|
||||
])
|
||||
.WithTextDisplay(instructions.ToString());
|
||||
}
|
||||
31
docs/guides/components_v2/samples/interactions.cs
Normal file
31
docs/guides/components_v2/samples/interactions.cs
Normal file
@@ -0,0 +1,31 @@
|
||||
private async Task ClientOnInteractionCreatedAsync(SocketInteraction arg)
|
||||
{
|
||||
switch (arg)
|
||||
{
|
||||
case SocketMessageComponent component:
|
||||
switch (component.Data.CustomId)
|
||||
{
|
||||
// Non dynamic cases ...
|
||||
|
||||
default:
|
||||
var customId = component.Data.CustomId;
|
||||
var lastPartStartIndex = customId.LastIndexOf('-');
|
||||
|
||||
if (lastPartStartIndex == -1)
|
||||
return;
|
||||
|
||||
if (customId[..lastPartStartIndex] == RecipesLookInsideButton) // "recipes-show-me-button"
|
||||
await component.UpdateAsync(m => m.Components = BuildComponentUnsafe(_recipes.First(r => r.RecipeId == int.Parse(customId[(lastPartStartIndex + 1)..]))).Build()); // _recipes is a list of Recipe objects ; int.Parse({recipe.RecipeId}) (in this case it is 1)
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
case SocketModal modal:
|
||||
// Interaction came from a modal
|
||||
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
}
|
||||
59
docs/guides/components_v2/samples/recipe-interactions.cs
Normal file
59
docs/guides/components_v2/samples/recipe-interactions.cs
Normal file
@@ -0,0 +1,59 @@
|
||||
private async Task ClientOnInteractionCreatedAsync(SocketInteraction arg)
|
||||
{
|
||||
switch (arg)
|
||||
{
|
||||
case SocketMessageComponent component:
|
||||
switch (component.Data.CustomId)
|
||||
{
|
||||
// SET SERVINGS BUTTON CLICKED
|
||||
case RecipeServingsModal:
|
||||
var servings = short.Parse(component.Message.Components.FindComponentById<TextDisplayComponent>(RecipeServingsDisplay).Content.Split(' ')[1]);
|
||||
|
||||
await component.RespondWithModalAsync(CreateServingsModal(servings).Build());
|
||||
|
||||
break;
|
||||
|
||||
// ITEM IN COMBOXBOX CHANGED
|
||||
case RecipeUnitInput:
|
||||
SelectMenuComponent selectedItem = component.Message.Components.FindComponentById<SelectMenuComponent>(RecipeUnitSelectMenu);
|
||||
var unitValue = short.Parse(component.Data.Values.First());
|
||||
var recipeName = component.Message.Components.FindComponentById<TextDisplayComponent>(RecipeNameDisplay).Content[2..];
|
||||
Recipe recipe = _recipes.First(r => r.Name == recipeName);
|
||||
Recipe recipe0 = recipe.Clone();
|
||||
var unit = (Units)Enum.ToObject(typeof(Units), unitValue);
|
||||
|
||||
ComponentBuilderV2 newComponentContainer = BuildComponentUnsafe(recipe0, unit);
|
||||
|
||||
await component.UpdateAsync(m => m.Components = newComponentContainer.Build());
|
||||
|
||||
break;
|
||||
default:
|
||||
// Ununsed here
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
// MODAL SUBMIT
|
||||
case SocketModal modal:
|
||||
if (modal.Data.CustomId == RecipeServingsButton)
|
||||
{
|
||||
var success = short.TryParse(modal.Data.Components.First(c => c.CustomId == RecipeServingsInput).Value, out var servings);
|
||||
|
||||
if (!success || servings <= 0)
|
||||
break;
|
||||
|
||||
Recipe recipe = _recipes.First(r => r.Name == modal.Message.Components.FindComponentById<TextDisplayComponent>(RecipeNameDisplay).Content[2..]);
|
||||
Recipe? recipe0 = recipe.Clone();
|
||||
|
||||
recipe0.ChangeServings(servings, true);
|
||||
|
||||
ComponentBuilderV2 newComponentContainer = BuildComponentUnsafe(recipe0);
|
||||
|
||||
await modal.UpdateAsync(m => m.Components = newComponentContainer.Build());
|
||||
}
|
||||
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
}
|
||||
15
docs/guides/components_v2/samples/recipe-servings-modal.cs
Normal file
15
docs/guides/components_v2/samples/recipe-servings-modal.cs
Normal file
@@ -0,0 +1,15 @@
|
||||
private static ModalBuilder CreateServingsModal(short servings)
|
||||
{
|
||||
TextInputBuilder? textInput = new TextInputBuilder()
|
||||
.WithCustomId(RecipeServingsInput)
|
||||
.WithLabel("Servings")
|
||||
.WithValue(servings.ToString())
|
||||
.WithMinLength(1)
|
||||
.WithMaxLength(3)
|
||||
.WithStyle(TextInputStyle.Short);
|
||||
|
||||
return new ModalBuilder()
|
||||
.WithCustomId(RecipeServingsButton)
|
||||
.WithTitle("Set Servings")
|
||||
.AddTextInput(textInput);
|
||||
}
|
||||
14
docs/guides/components_v2/samples/recipes-command.cs
Normal file
14
docs/guides/components_v2/samples/recipes-command.cs
Normal file
@@ -0,0 +1,14 @@
|
||||
[SlashCommand("recipes", "Gets all recipes")]
|
||||
public async Task GetRecipesAsync()
|
||||
{
|
||||
MessageComponent? embed = (await recipeService.GetRecipesComponentAsync())?.Build();
|
||||
|
||||
if (embed is null)
|
||||
{
|
||||
await RespondAsync($"No recipes found.", ephemeral: true);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
await RespondAsync(components: embed);
|
||||
}
|
||||
32
docs/guides/components_v2/samples/recipes-component.cs
Normal file
32
docs/guides/components_v2/samples/recipes-component.cs
Normal file
@@ -0,0 +1,32 @@
|
||||
private async Task<ComponentBuilderV2> BuildComponentsUnsafeAsync()
|
||||
{
|
||||
if (!_recipes.Any()) // _recipes is simply a list of recipe objects
|
||||
{
|
||||
return new ComponentBuilderV2()
|
||||
.WithTextDisplay(
|
||||
"""
|
||||
# No recipes found
|
||||
You should consider adding some.
|
||||
""");
|
||||
}
|
||||
|
||||
var builder = new ComponentBuilderV2();
|
||||
Emote? emote = await _clientProvider.Client.GetApplicationEmoteAsync(1393996479357517925);
|
||||
|
||||
foreach (Recipe recipe in _recipes)
|
||||
{
|
||||
var buttonBuilder = new ButtonBuilder("Look inside", $"{RecipesLookInsideButton}-{recipe.RecipeId}"); // RecipesLookInsideButton is a constant string
|
||||
|
||||
if (emote is not null)
|
||||
buttonBuilder.WithEmote(emote);
|
||||
|
||||
builder
|
||||
.WithTextDisplay($"# {recipe.Name}")
|
||||
.WithMediaGallery(["https://cdn.discordapp.com/attachments/964253122547552349/1336440069892083712/7Q3S.gif?ex=67a3d04e&is=67a27ece&hm=059c9d28466f43a50c4b450ca26fc01298a2080356421d8524384bf67ea8f3ab&"])
|
||||
.WithActionRow([
|
||||
buttonBuilder
|
||||
]);
|
||||
}
|
||||
|
||||
return builder;
|
||||
}
|
||||
Reference in New Issue
Block a user