v3.0.0-alpha.13 | New pagination, component factories and Spring support
Overview
Reworked pagination, added factories for buttons and select menus, added Spring support and other utilities.
Reworked pagination (#159)
Pagination was overhauled to take advantage of dependency injection, to have better extensibility, to support coroutines and Kotlin's Duration
.
Name changes
ChoiceMenu
->ButtonMenu
InteractiveMenu
->NestedPagination
Usage changes
- A
Paginators
service that serves as a pagination factory has to be used, improving discoverability - Mandatory parameters are no longer behind setters, they are requested by the factory, reducing errors
New features
ButtonMenu
can have different a button style on each entryButtonMenu
can have its buttons reused, in which case the callback can be called more than once- Added support for Kotlin coroutines and
Duration
- Some callbacks (like
PageEditor
) cannot use coroutines as they are called by methods overridable by Java users
- Some callbacks (like
NestedPagination
saves the page number before switching
Changes
- Most options use default values, such as paginator buttons and timeouts
- Requesting a new page invalidates the replaced page's components, can be disabled
- Paginators expire by default using the same timeout as in
Components
- Timeout consumers are optional, timeout can be entirely disabled
- Page editors no longer require returning an embed, you can freely edit the message and/or the existing embed
Extension changes
- Builders are passed instead of their individual values
- Creating a message from the pagination's state is fully handled by the base class, and decomposed into steps that can be overridden
Added factories for buttons and select menus, intermediary step to choose component lifetime (#160)
Components are now created in their own factories, Buttons
for buttons, and SelectMenus
for... select menus.
This solves conflicts with the components
property in JDA-KTX builders, and allows for shorter and more maintainable code, as ephemeral/persistent overloads are no longer needed.
Creating component groups and deleting components can still be done in Components
, or any of those two classes.
- Added an intermediary component factory, which lets you choose whether a component is ephemeral or persistent
- Added
primary
/secondary
/success
/danger
/link
overloads to create buttons with predefined styles - Removed overloads that let you construct empty (invalid) buttons
- Added docs
- Added
ButtonContent#withEmoji
- Deprecated old
Components
methods - Deprecated
Components#deleteComponentsById
, replaced withdeleteComponentsByIds
Button example
Creating a button - Before
fun onSlashCommand(event: GuildSlashEvent, components: Components) {
val button = components.ephemeralButton(ButtonStyle.DANGER, emoji = EmojiUtils.resolveJDAEmoji("wastebasket")) {
// ...
}
}
Creating a button - After
fun onSlashCommand(event: GuildSlashEvent, buttons: Buttons) {
val button = buttons.danger(EmojiUtils.resolveJDAEmoji("wastebasket")).ephemeral {
// ...
}
}
Select menu example
Creating a select menu - Before
fun onSlashCommand(event: GuildSlashEvent, components: Components) {
val selectMenu = components.ephemeralStringSelectMenu {
// ...
}
}
Creating a select menu - After
fun onSlashCommand(event: GuildSlashEvent, selectMenus: SelectMenus) {
val selectMenu = selectMenus.stringSelectMenu().ephemeral {
// ...
}
}
Component group example
Creating a component group - Before
fun onSlashCommand(event: GuildSlashEvent, components: Components) {
val button: Button = TODO()
val selectMenu: StringSelectMenu = TODO()
val group = components.ephemeralGroup(button, selectMenu) {
// ...
}
}
Creating a component group - After
fun onSlashCommand(event: GuildSlashEvent, components: Components/Buttons/SelectMenus) {
val button: Button = TODO()
val selectMenu: StringSelectMenu = TODO()
val group = components.group(button, selectMenu).ephemeral {
// ...
}
}
Added declaration sites to command, autocomplete and rate limit declarations
When an error occurs when declaring a command, the error contains a reference to the method linked to the error.
This works great for annotated declarations, but for code declarations, this meant that there was no way of knowing where the declaration was done.
To fix that, everytime a command (etc...) is declared, the call site (i.e. the line where the command was created) is saved in a DeclarationSite
,
which will then be used in the error, pointing to the actual declaration.
In case you are using an utility class to declare your commands/autocomplete/rate limits, you can always use @IgnoreStackFrame
,
so the declaration site is the one which calls your utility class, instead of the utility class itself.
Added Spring support (#162)
The built-in dependency can now be replaced with Spring IoC.
Additions
- Added
@EnableBotCommands
as a Spring entry point - Added application properties for most configurations
- Added
JDAConfiguration
, containing intents and cache flags, you can use it for yourJDAService
- Added configurers, letting you configure the framework using code, in case the application properties aren't enough
- Added
@RequiresDatabase
and@RequiresComponents
- It is recommended to replace
@Dependencies
on(Blocking)Database
/Components
/Buttons
/SelectMenus
with them
- It is recommended to replace
Changes
CoroutineEventManager
is no longer passed to theBotCommands
entry point and has been deprecated- Must now implement
ICoroutineEventManagerSupplier
in a service - A default provider with 4 threads is used as fallback
- Must now implement
- [Small breaking] The
ServiceContainer
API was slightly altered, but no behavior changed, this should not affect anyone - [Small breaking] You can no longer put services using
BContext
, useServiceContainer
instead - [Small breaking]
BContext
parameter is no longer passed inClassGraphProcessor
(s), this should not affect anyone - [Small breaking]
BContext
parameter was replaced withServiceContainer
inConditionalServiceChecker
andCustomConditionChecker
New features
Built-in dependency injection
- Added
@IgnoreServiceTypes
- Used to ignore types added by implementing an interface annotated with
@InterfacedService
- Used to ignore types added by implementing an interface annotated with
Parameter resolvers
- Added top-level
resolverFactory
to create resolver factory
Misc
- Added
MessageCreate/EditData
extensions - Added
RestAction<InteractionHook>.deleteDelayed
Changes
Configuration
- Command localization locales store
DiscordLocale
instead ofLocale
Built-in dependency injection
- Improved error messages
- Allow
@Dependencies
on functions and getters
Application commands
- [Small breaking] Moved
ApplicationGeneratedValueSupplier
tocommands.application
package - Added a check to prevent mixing top-level commands and subcommands
- Allow declaring application commands with the same name if they are of different type
Components
- Added
asDisabled
/asEnabled
on buttons and select menus - [Small breaking] Added
ButtonStyle
inButtonContent
- [Small breaking] Refactored InteractionConstraints
Parameter resolvers
- Exposed
TypedParameterResolverFactory#type
Misc
- [Small breaking] Renamed
KotlinLogging.logger
tologgerOf
, to help with conflicts - Keep RestAction type in
deleteDelayed
extension - Show app owner and ID in logs if exception dispatch fails
Removals
Components
- [Non-trivial breaking] Removed default timeout on persistent components, meaning they will no longer expire automatically
Fixes
Components
- Fixed deleting components by IDs
- Fixed missing annotation detection on resolver factories
Don't hesitate to check out the changelogs and the wiki.
Full Changelog: v3.0.0-alpha.12...v3.0.0-alpha.13