mirror of
https://github.com/PluralKit/PluralKit.git
synced 2026-02-12 00:30:11 +00:00
Compare commits
7 commits
ccbc027729
...
4293f26b8a
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4293f26b8a | ||
|
|
bb0f27a70d | ||
|
|
21ec6ce022 | ||
|
|
ceedf8a327 | ||
|
|
cd42131b3f | ||
|
|
26208ce16c | ||
|
|
a55ccdceea |
7 changed files with 280 additions and 28 deletions
|
|
@ -7,12 +7,94 @@ namespace PluralKit.Bot;
|
|||
|
||||
public class Help
|
||||
{
|
||||
public Task HelpRoot(Context ctx)
|
||||
{
|
||||
if (ctx.MatchFlag("show-embed", "se"))
|
||||
return HelpRootOld(ctx);
|
||||
|
||||
return ctx.Reply(BuildComponents(ctx.Author.Id, Help.Description.Replace("{prefix}", ctx.DefaultPrefix), -1));
|
||||
}
|
||||
|
||||
public static Task ButtonClick(InteractionContext ctx, string prefix)
|
||||
{
|
||||
if (!ctx.CustomId.Contains(ctx.User.Id.ToString()))
|
||||
return ctx.Ignore();
|
||||
|
||||
if (ctx.CustomId.StartsWith("new-"))
|
||||
{
|
||||
Console.WriteLine($"{ctx.Event.Message.Components.First().Components.Length}");
|
||||
if (ctx.Event.Message.Components.First().Components[1].Components.Where(x => x.CustomId == ctx.CustomId).First().Style == ButtonStyle.Primary)
|
||||
return ctx.Respond(InteractionResponse.ResponseType.UpdateMessage, new()
|
||||
{
|
||||
Components = BuildComponents(ctx.User.Id, Help.Description.Replace("{prefix}", prefix), -1),
|
||||
Flags = Message.MessageFlags.IsComponentsV2,
|
||||
});
|
||||
|
||||
var text = helpEmbedPages.GetValueOrDefault(ctx.CustomId.Split("-")[3]).Select(
|
||||
(item, index) => $"### {item.Name.Replace("{prefix}", prefix)}\n{item.Value.Replace("{prefix}", prefix)}"
|
||||
).ToArray();
|
||||
|
||||
var index = Array.FindIndex(ctx.Event.Message.Components.First().Components[1].Components, x => x.CustomId == ctx.CustomId);
|
||||
var components = BuildComponents(ctx.User.Id, Help.Description.Replace("{prefix}", prefix), index);
|
||||
|
||||
components.First().Components[ctx.Event.Message.Components.First().Components.Length - 1] = new MessageComponent()
|
||||
{
|
||||
Type = ComponentType.Text,
|
||||
Content = String.Join("\n", text),
|
||||
};
|
||||
|
||||
return ctx.Respond(InteractionResponse.ResponseType.UpdateMessage, new()
|
||||
{
|
||||
Components = components,
|
||||
Flags = Message.MessageFlags.IsComponentsV2,
|
||||
});
|
||||
}
|
||||
|
||||
return ButtonClickOld(ctx, prefix);
|
||||
}
|
||||
|
||||
private static MessageComponent[] BuildComponents(ulong userId, string textContent, int menuIndex)
|
||||
{
|
||||
return [
|
||||
new MessageComponent()
|
||||
{
|
||||
Type = ComponentType.Container,
|
||||
AccentColor = DiscordUtils.Blue,
|
||||
Components = [
|
||||
new MessageComponent()
|
||||
{
|
||||
Type = ComponentType.Text,
|
||||
Content = "# PluralKit\n-# Use the buttons below to see more info!"
|
||||
},
|
||||
helpPageButtons(userId, "new-", menuIndex),
|
||||
new MessageComponent()
|
||||
{
|
||||
Type = ComponentType.Separator,
|
||||
},
|
||||
new MessageComponent()
|
||||
{
|
||||
Type = ComponentType.Text,
|
||||
Content = textContent,
|
||||
},
|
||||
],
|
||||
},
|
||||
new MessageComponent()
|
||||
{
|
||||
Type = ComponentType.Text,
|
||||
Content = EmbedFooter("\n-# "),
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
///
|
||||
|
||||
private static string Description = "PluralKit is a bot designed for plural communities on Discord, and is open for anyone to use. It allows you to register systems, maintain system information, set up message proxying, log switches, and more.\n\n" +
|
||||
"**System recovery:** in the case of your Discord account getting lost or deleted, the PluralKit staff can help you recover your system, **only if you save the system token from `{prefix}token`**. See [this FAQ entry](https://pluralkit.me/faq/#can-i-recover-my-system-if-i-lose-access-to-my-discord-account) for more details.\n\n" +
|
||||
"If PluralKit is useful to you, please consider donating on [Patreon](https://patreon.com/pluralkit) or [Buy Me A Coffee](https://buymeacoffee.com/pluralkit).\n" +
|
||||
"## Use the buttons below to see more info!";
|
||||
"If PluralKit is useful to you, please consider donating on [Patreon](https://patreon.com/pluralkit) or [Buy Me A Coffee](https://buymeacoffee.com/pluralkit).";
|
||||
|
||||
public static string EmbedFooter = "-# PluralKit by @ske and contributors | Myriad design by @layl, icon by @tedkalashnikov, banner by @fulmine | GitHub: https://github.com/PluralKit/PluralKit/ | Website: https://pluralkit.me/";
|
||||
private static string DescriptionOld = $"{Description}\n## Use the buttons below to see more info!";
|
||||
|
||||
public static string EmbedFooter(string linkSeparator) => $"-# PluralKit by @ske and contributors | Myriad design by @layl, icon by @tedkalashnikov, banner by @fulmine{linkSeparator}GitHub: https://github.com/PluralKit/PluralKit/ | Website: https://pluralkit.me/";
|
||||
|
||||
public static Embed helpEmbed = new()
|
||||
{
|
||||
|
|
@ -98,7 +180,7 @@ public class Help
|
|||
}
|
||||
};
|
||||
|
||||
private static MessageComponent helpPageButtons(ulong userId) => new MessageComponent
|
||||
private static MessageComponent helpPageButtons(ulong userId, string pfx = "", int menuIndex = -1) => new MessageComponent
|
||||
{
|
||||
Type = ComponentType.ActionRow,
|
||||
Components = new[]
|
||||
|
|
@ -106,58 +188,54 @@ public class Help
|
|||
new MessageComponent
|
||||
{
|
||||
Type = ComponentType.Button,
|
||||
Style = ButtonStyle.Secondary,
|
||||
Style = menuIndex == 0 ? ButtonStyle.Primary : ButtonStyle.Secondary,
|
||||
Label = "Basic Info",
|
||||
CustomId = $"help-menu-basicinfo-{userId}",
|
||||
CustomId = $"{pfx}help-menu-basicinfo-{userId}",
|
||||
Emoji = new() { Name = "\u2139" },
|
||||
},
|
||||
new()
|
||||
{
|
||||
Type = ComponentType.Button,
|
||||
Style = ButtonStyle.Secondary,
|
||||
Style = menuIndex == 1 ? ButtonStyle.Primary : ButtonStyle.Secondary,
|
||||
Label = "Getting Started",
|
||||
CustomId = $"help-menu-gettingstarted-{userId}",
|
||||
CustomId = $"{pfx}help-menu-gettingstarted-{userId}",
|
||||
Emoji = new() { Name = "\u2753", },
|
||||
},
|
||||
new()
|
||||
{
|
||||
Type = ComponentType.Button,
|
||||
Style = ButtonStyle.Secondary,
|
||||
Style = menuIndex == 2 ? ButtonStyle.Primary : ButtonStyle.Secondary,
|
||||
Label = "Useful Tips",
|
||||
CustomId = $"help-menu-usefultips-{userId}",
|
||||
CustomId = $"{pfx}help-menu-usefultips-{userId}",
|
||||
Emoji = new() { Name = "\U0001f4a1", },
|
||||
|
||||
},
|
||||
new()
|
||||
{
|
||||
Type = ComponentType.Button,
|
||||
Style = ButtonStyle.Secondary,
|
||||
Style = menuIndex == 3 ? ButtonStyle.Primary : ButtonStyle.Secondary,
|
||||
Label = "More Info",
|
||||
CustomId = $"help-menu-moreinfo-{userId}",
|
||||
CustomId = $"{pfx}help-menu-moreinfo-{userId}",
|
||||
Emoji = new() { Id = 986379675066593330, },
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
public Task HelpRoot(Context ctx)
|
||||
public Task HelpRootOld(Context ctx)
|
||||
=> ctx.Rest.CreateMessage(ctx.Channel.Id, new MessageRequest
|
||||
{
|
||||
Content = $"{Emojis.Warn} If you cannot see the rest of this message see [the FAQ](<https://pluralkit.me/faq/#why-do-most-of-pluralkit-s-messages-look-blank-or-empty>)",
|
||||
Embeds = new[] { helpEmbed with { Description = Help.Description.Replace("{prefix}", ctx.DefaultPrefix), Fields = new Embed.Field[] { new("", EmbedFooter) } } },
|
||||
Embeds = new[] { helpEmbed with { Description = Help.DescriptionOld.Replace("{prefix}", ctx.DefaultPrefix), Fields = new Embed.Field[] { new("", EmbedFooter(" | ")) } } },
|
||||
Components = new[] { helpPageButtons(ctx.Author.Id) },
|
||||
});
|
||||
|
||||
public static Task ButtonClick(InteractionContext ctx, string prefix)
|
||||
public static Task ButtonClickOld(InteractionContext ctx, string prefix)
|
||||
{
|
||||
if (!ctx.CustomId.Contains(ctx.User.Id.ToString()))
|
||||
return ctx.Ignore();
|
||||
|
||||
var buttons = helpPageButtons(ctx.User.Id);
|
||||
|
||||
if (ctx.Event.Message.Components.First().Components.Where(x => x.CustomId == ctx.CustomId).First().Style == ButtonStyle.Primary)
|
||||
return ctx.Respond(InteractionResponse.ResponseType.UpdateMessage, new()
|
||||
{
|
||||
Embeds = new[] { helpEmbed with { Description = Help.Description.Replace("{prefix}", prefix), Fields = new Embed.Field[] { new("", EmbedFooter) } } },
|
||||
Embeds = new[] { helpEmbed with { Description = Help.DescriptionOld.Replace("{prefix}", prefix), Fields = new Embed.Field[] { new("", EmbedFooter(" | ")) } } },
|
||||
Components = new[] { buttons }
|
||||
});
|
||||
|
||||
|
|
@ -167,7 +245,7 @@ public class Help
|
|||
{
|
||||
Embeds = new[] { helpEmbed with { Fields = helpEmbedPages.GetValueOrDefault(ctx.CustomId.Split("-")[2]).Select(
|
||||
(item, index) => new Embed.Field(item.Name.Replace("{prefix}", prefix), item.Value.Replace("{prefix}", prefix))
|
||||
).Append(new("", EmbedFooter)).ToArray() } },
|
||||
).Append(new("", EmbedFooter(" | "))).ToArray() } },
|
||||
Components = new[] { buttons }
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -92,7 +92,7 @@ public class Misc
|
|||
+ $"**{stats.db.switches:N0}** switches, **{stats.db.messages:N0}** messages\n" +
|
||||
$"**{stats.db.guilds:N0}** servers with **{stats.db.channels:N0}** channels"));
|
||||
|
||||
embed.Field(new("", Help.EmbedFooter));
|
||||
embed.Field(new("", Help.EmbedFooter(" | ")));
|
||||
|
||||
var uptime = ((DateTimeOffset)process.StartTime).ToUnixTimeSeconds();
|
||||
embed.Description($"### PluralKit [{BuildInfoService.Version}](https://github.com/pluralkit/pluralkit/commit/{BuildInfoService.FullVersion})\n" +
|
||||
|
|
|
|||
|
|
@ -75,7 +75,7 @@ public class EmbedService
|
|||
if (system.Tag != null)
|
||||
headerText += $"\n**Tag:** {system.Tag.EscapeMarkdown()}";
|
||||
|
||||
if (cctx.Config.CardShowColorHex && !system.Color.EmptyOrNull())
|
||||
if (cctx.Config != null && cctx.Config.CardShowColorHex && !system.Color.EmptyOrNull())
|
||||
headerText += $"\n**Color:** #{system.Color}";
|
||||
|
||||
if (cctx.Guild != null)
|
||||
|
|
@ -119,7 +119,7 @@ public class EmbedService
|
|||
}
|
||||
|
||||
List<MessageComponent> descComponents = [];
|
||||
if (system.DescriptionFor(ctx) is { } desc)
|
||||
if (system.DescriptionFor(ctx) is { } desc && !string.IsNullOrWhiteSpace(desc))
|
||||
{
|
||||
descComponents.Add(new()
|
||||
{
|
||||
|
|
@ -361,7 +361,7 @@ public class EmbedService
|
|||
headerText += $"\n**Display name:** {member.DisplayName.Truncate(1024)}";
|
||||
if (guild != null && guildDisplayName != null)
|
||||
headerText += $"\n**Server nickname (for '{guild.Name}'):** {guildDisplayName.Truncate(1024)}";
|
||||
if (ccfg.CardShowColorHex && !member.Color.EmptyOrNull())
|
||||
if (ccfg != null && ccfg.CardShowColorHex && !member.Color.EmptyOrNull())
|
||||
headerText += $"\n**Color:** #{member.Color}";
|
||||
if (member.PronounsFor(ctx) is { } pronouns && !string.IsNullOrWhiteSpace(pronouns))
|
||||
headerText += $"\n**Pronouns:** {pronouns}";
|
||||
|
|
@ -405,7 +405,7 @@ public class EmbedService
|
|||
}
|
||||
|
||||
List<MessageComponent> descComponents = [];
|
||||
if (member.DescriptionFor(ctx) is { } desc)
|
||||
if (member.DescriptionFor(ctx) is { } desc && !string.IsNullOrWhiteSpace(desc))
|
||||
{
|
||||
descComponents.Add(new()
|
||||
{
|
||||
|
|
@ -582,7 +582,7 @@ public class EmbedService
|
|||
if (target.NamePrivacy.CanAccess(pctx) && target.DisplayName != null)
|
||||
headerText += $"\n**Display name:** {target.DisplayName}";
|
||||
|
||||
if (ctx.Config.CardShowColorHex && !target.Color.EmptyOrNull())
|
||||
if (ctx.Config != null && ctx.Config.CardShowColorHex && !target.Color.EmptyOrNull())
|
||||
headerText += $"\n**Color:** #{target.Color}";
|
||||
|
||||
if (target.ListPrivacy.CanAccess(pctx))
|
||||
|
|
@ -595,7 +595,7 @@ public class EmbedService
|
|||
}
|
||||
|
||||
List<MessageComponent> descComponents = [];
|
||||
if (target.DescriptionFor(pctx) is { } desc)
|
||||
if (target.DescriptionFor(pctx) is { } desc && !string.IsNullOrWhiteSpace(desc))
|
||||
{
|
||||
descComponents.Add(new()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -9,6 +9,51 @@ the below is a lightly edited copy of the changelog messages posted on discord.
|
|||
|
||||
a more complete list of code changes can be found [in the git repo](https://github.com/pluralkit/pluralkit/commits/main)
|
||||
|
||||
## 2025-09-08
|
||||
|
||||
### new/updated
|
||||
- **new "ComponentsV2" format for system/member/group cards and help menu** (use -show-embed or -se flag to get the old view)
|
||||
- [we have written a blog post giving some context behind this change](/posts/2025-09-08-components-v2/) - please read this also!
|
||||
- color codes are now hidden by default on cards, and a config option to show them again was added: `pk;config show color on`
|
||||
- **new status page at <https://status.pluralkit.me>**
|
||||
- replies to commands can now be deleted forever (previously 24h)
|
||||
- logclean support for [Zeppelin](https://zeppelin.gg/) bot
|
||||
- `pk;system` command now can be used with `pk;account` alias
|
||||
- creating a new system now shows a note about the terms of service
|
||||
- the announcements/changelog are now cross-posted from discord to the website
|
||||
- `pk;member <member> name` command now can show the member name as well as setting it
|
||||
- clarified wording and updated formatting for some messages
|
||||
|
||||
### fixed
|
||||
- reply embeds now strip out excessive newlines
|
||||
- cleaned up some error messages
|
||||
- bot now correctly checks privacy in a few commands
|
||||
- made a better attempt to not delete images uploaded to CDN on export/import
|
||||
- importing system data with a large amount of switches should no longer throw an error
|
||||
|
||||
### API changes
|
||||
- api no longer breaks when the redis server is restarted
|
||||
- some error messages have been fixed to use the correct JSON format
|
||||
- document that short IDs are accepted in any format displayable by the bot
|
||||
- added public/unauthenticated partial view for `/systems/:id/settings` endpoint
|
||||
- autoproxy endpoint now allows changing the currently latched member
|
||||
- discord guild endpoints now try harder at checking if the system is in the guild
|
||||
- many docs fixes
|
||||
|
||||
### Internal changes
|
||||
- updated docker-compose configuration for self-hosting
|
||||
- modernised the development documentation
|
||||
- the Myriad Discord library has been relicensed to MIT to facilitate external use
|
||||
- the C# code now correctly builds in Visual Studio 2022
|
||||
- the C# services now log in JSON format; this required a fork of Serilog and thus a git submodule
|
||||
- code to generate colour previews has been rewritten, since the third-party site went offline
|
||||
- fixed a bug where shards would never reconnect and require manual intervention
|
||||
- bumped Rust language version to 2024
|
||||
- rewrote scheduled tasks and database migrations in Rust
|
||||
- the Rust entrypoint macro has been rewritten as a proc macro to clean up call sites
|
||||
- all (well, most) Rust errors correctly use fields for values instead of formatting them into the error string
|
||||
- gateway events are now sent to the C# bot code through HTTP
|
||||
|
||||
## 2025-01-01
|
||||
|
||||
### Added
|
||||
|
|
|
|||
|
|
@ -148,6 +148,7 @@ You can have a space after `pk;`, e.g. `pk;system` and `pk; system` will do the
|
|||
- `pk;config split IDs [on|off]` - Toggles whether to display 6-letter IDs with a hyphen, to ease readability.
|
||||
- `pk;config capitalize IDs [on|off]` - Toggles whether to display IDs as capital letters, to ease readability.
|
||||
- `pk;config pad IDs [left|right|off]` - Toggles whether to pad (add a space) 5-character IDs in lists.
|
||||
- `pk;config show color [on|off]` - Toggles whether to show color codes in system/member/group cards
|
||||
- `pk;config proxy switch [new|add|off]` - Toggles whether to log a switch whenever you proxy as a different member (or add member to recent switch in add mode).
|
||||
- `pk;config name format [format]` - Changes your system's username formatting.
|
||||
- `pk;config server name format [format]` - Changes your system's username formatting for the current server.
|
||||
|
|
|
|||
127
docs/content/posts/2025-09-08-components-v2.md
Normal file
127
docs/content/posts/2025-09-08-components-v2.md
Normal file
|
|
@ -0,0 +1,127 @@
|
|||
---
|
||||
title: on the switch to Components V2
|
||||
permalink: /posts/2025-09-08-components-v2/
|
||||
---
|
||||
|
||||
## on the switch to Components V2
|
||||
|
||||
you probably will have noticed the new design of system/member/group cards
|
||||
in PluralKit. we know that a lot of people will have questions as to why
|
||||
we've suddenly changed the layout & design of the cards, so we hope this
|
||||
post can explain some of the decisions that went into these.
|
||||
|
||||
### why change the cards at all?
|
||||
|
||||
the old cards used something Discord calls "embeds." embeds were initially
|
||||
only meant for showing details about a link posted in chat, but were later
|
||||
also used by Discord bots for displaying information in a structured way.
|
||||
|
||||
embeds are extremely limited in their layout, and bots have very little
|
||||
control over how things are displayed in them. in addition, a lot of newer
|
||||
Discord features (things like the Markdown headers, or small text) either
|
||||
don't display in embeds at all, or only display on some platforms - making
|
||||
them very inconsistent in how they display.
|
||||
|
||||
the new cards use Discord's "Components V2" - which has been designed by
|
||||
Discord from the ground up specifically for bots to use for custom content.
|
||||
Components V2 is much more flexible, and fixes a lot of the issues with the
|
||||
old embeds (the Markdown headers / small text being one example), letting us
|
||||
have a lot more control over the display of the cards.
|
||||
|
||||
Components V2 is the way forward, as far as Discord is concerned - meaning
|
||||
that some of the issues with embeds will never be fixed in embeds themselves,
|
||||
necessitating a move to Components V2.
|
||||
|
||||
### continual improvement (also: "where'd my proxy avatar go?")
|
||||
|
||||
currently, the only thing missing from PluralKit's new Components V2 cards
|
||||
(compared to the previous embed-based cards) is member proxy avatars. on
|
||||
the old member cards, proxy avatars would display as a tiny circle at the
|
||||
top left. there is not currently a way to display an image of that size/
|
||||
position in Components V2... but from what we understand, that is on the
|
||||
list of things Discord will be adding in the future. which leads into the
|
||||
next point:
|
||||
|
||||
unlike embeds, which have remained stagnant for years, Discord are actively
|
||||
working on adding *new functionality* to Components V2, as well as fixing
|
||||
whatever issues arise - in order to take advantage of new functionality as
|
||||
Discord release it, we would have needed to move to Components V2 at some
|
||||
point. we figured that with the state Components V2 is currently in, now
|
||||
was a good time to make that switch!
|
||||
|
||||
### character limits
|
||||
|
||||
another advantage of Components V2 over embeds is the character limit for
|
||||
cards. the old embeds had a hard limit of 1024 characters in a single field,
|
||||
with a limit of 2000 characters for the entire embed. this is the reason that
|
||||
PK descriptions are capped at 1000 characters.
|
||||
|
||||
Components V2, however, has a character limit of *6000* characters across
|
||||
the entire card, which can be split however we like. this means that once the
|
||||
old embed-based cards are removed, we will be able to raise the description
|
||||
character limit!
|
||||
|
||||
### where'd the color codes go?
|
||||
|
||||
one of the design choices we made for the new system/member/group cards was
|
||||
to hide the hex color codes by default - this has been a near-constantly
|
||||
requested feature, and the Components V2 rework gave us a good opportunity
|
||||
to implement it.
|
||||
|
||||
we added a configuration toggle for this - if you *do* want to see the hex
|
||||
codes for colors, you can use `pk;config show color on` to re-enable them.
|
||||
|
||||
### other small improvements
|
||||
|
||||
- Components V2 allows us to use real code blocks in the card footers for
|
||||
things like system/member/group IDs. on mobile Discord clients, this makes
|
||||
copying IDs a lot easier - you can copy an individual code block's content
|
||||
by tapping on it
|
||||
- having a banner image set no longer makes the description width smaller
|
||||
- on mobile clients, it is now a lot easier to view any images larger, just
|
||||
by tapping on them
|
||||
- some PluralKit users who use screen readers have reported that the new
|
||||
Components V2 cards are read by their screen readers in a much more easily
|
||||
understood way
|
||||
|
||||
### the new cards don't show up! / is there a way to see the old cards?
|
||||
|
||||
Components V2 is not supported on older Discord clients. there is nothing
|
||||
we can do about this, other than encourage you to update your Discord
|
||||
client.
|
||||
|
||||
however - for now, using the `-show-embed` (or `-se`) flag to the
|
||||
`pk;system`, `pk;member`, and `pk;group` commands will show the old
|
||||
embed-based cards.
|
||||
|
||||
the old cards will still show in some places in the bot (the most prominent
|
||||
example being when querying message info with the ❓ reaction) also,
|
||||
until we migrate those parts of the bot to use Components V2.
|
||||
|
||||
the old embed-based cards **will be removed from the bot in future** -
|
||||
although we do not have any specific timeframe in mind for this yet.
|
||||
because of this, we will not be supporting a way to persistently show
|
||||
the old cards (such as a config option) - the `-show-embed` flag is the
|
||||
only way to pull up the old cards when using a command to query info.
|
||||
|
||||
### in closing
|
||||
|
||||
we hope that this gives you a bit more context as to why we've made this
|
||||
change - although there are some new design choices here, this was not
|
||||
a change made just for the sake of changing. moving to Components V2 not only
|
||||
gives us a lot more freedom to do things that weren't previously possible,
|
||||
but means we can fix a lot of the long-standing issues with PK cards!
|
||||
|
||||
we know this is a significant change for PluralKit, but we hope you can
|
||||
understand that this is a change for the better.
|
||||
|
||||
a lot of the decisions that went into the new versions of the cards were
|
||||
iterated on with feedback from members of the community who help beta test
|
||||
new PluralKit features - i want to thank those people immensely for their
|
||||
input!
|
||||
|
||||
if you'd like to help beta-test new features in future, check out the pins
|
||||
in the `#beta-testing` channel in [the support server](https://discord.gg/PczBt78)
|
||||
for the beta testing announcement role.
|
||||
|
||||
if you have any questions, please let us know in the support server!
|
||||
|
|
@ -4,5 +4,6 @@ title: Announcements & other posts
|
|||
|
||||
# Announcements & other posts
|
||||
|
||||
- 2025-09-08: [on the switch to Components V2](/posts/2025-09-08-components-v2/)
|
||||
- 2025-01-14: [january 2025 funding update](/posts/2025-01-14-funding-update/)
|
||||
- 2024-12-05: [late 2024 downtime notes & funding update](/posts/2024-12-05-downtime-notes/)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue