Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement interactive components #233

Open
LeadcodeDev opened this issue Jan 18, 2025 · 0 comments · Fixed by #234
Open

Implement interactive components #233

LeadcodeDev opened this issue Jan 18, 2025 · 0 comments · Fixed by #234
Assignees

Comments

@LeadcodeDev
Copy link
Member

Context

Within the Discord API there are a number of components such as buttons, select menu which allow an action to be performed as a result of another action from a user.

Example:
A new member joins the Discord server, under their welcome message is a button that sends a Hello ${member.username} message when a user clicks on it.

In this example, we can break the process down into several steps:

  1. Sending a message containing the button component
  2. Click by a user
  3. Sending a Hello ${member.username} message

In this process, we receive the action of the click (2) thanks to the interactionCreate event via the websocket and then, once redispatched, the developer can interact with it via a reaction.

This process is not practical for a developer who has to break down a "unified" flow into several listeners.

Proposal

In order to simplify the integration of this flow, we would like to propose an approach that allows the action performed on a component to be grouped with a handler.

We can therefore envisage a simple approach as shown below:

final myButton = Button.primary(
  uniqueId: '1234',
  label: 'Clic me',
  handle: (ctx) => print(ctx)
);

To enable the handler to be retrieved and executed, we need to store it using our IoC in a dedicated service in a simple format.

typedef ComponentHandler = ({
  String uniqueId,
  Future<void> Function(ComponentContext ctx) handler
});

If the button is sent a first time with a message during the application's lifecycle, then the trigger will find the association between uniqueId and the associated handler.

A class-based approach could be considered:

abstract interface class InteractiveComponent<T extends Component> {
  String get uniqueId;
  
  FutureOr<void> handle(ctx);
  T build();
}
final class MyButtonComponent implements InteractiveComponent {
  @override
  final String uniqueKey = '1234';

  @override
  FutureOr<void> handle(ctx) { ... }

  @override
  T build() => Button.primary(
    label: 'Clic me',
  );
}

Problem

If the function containing the button is never called, the ComponentHandler association will not exist and no action will be executed.

Solution

To solve this problem, we can consider 2 approaches:

  1. We need to declare the components in a file read during the boot time which would allow the systematic and automatic registration (via a constructor?) of the ComponentHandler as soon as it is started.
  2. The same principle as above, but with explicit registration in the client builder.
@LeadcodeDev LeadcodeDev self-assigned this Jan 18, 2025
@LeadcodeDev LeadcodeDev converted this from a draft issue Jan 18, 2025
@LeadcodeDev LeadcodeDev linked a pull request Jan 21, 2025 that will close this issue
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
Status: Backlog
1 participant