getButtonPress method
- Message message
inherited
Wait for a user to press on any button on a given message and return a context representing the button press.
You might also be interested in:
- awaitButtonPress, for getting a press from a single button;
- getButtonSelection, for getting a value from a button selection;
- getSelection, for getting a selection from a multi-select menu.
Implementation
@override
Future<ButtonComponentContext> getButtonPress(Message message) async {
if (_delegate != null) {
return _delegate!.getButtonPress(message);
}
final componentIds = message.components
?.expand(
(component) => component is ActionRowComponent ? component.components : [component])
.whereType<ButtonComponent>()
.where((element) => element.customId != null)
.map((component) => ComponentId.parse(component.customId!))
.toList() ??
[];
if (componentIds.any((element) => element == null)) {
throw UncaughtCommandsException(
'Buttons in getButtonPress must have an ID set with ComponentId.generate()',
_nearestCommandContext,
);
}
int remaining = componentIds.length;
Completer<ButtonComponentContext> completer = Completer();
for (final id in componentIds) {
commands.eventManager.nextButtonEvent(id!).then((context) {
if (completer.isCompleted) {
return;
}
completer.complete(context);
}).catchError((Object error, StackTrace stackTrace) {
remaining--;
if (remaining == 0 && !completer.isCompleted) {
// All the futures failed with an exception, throw the latest one back to the user
if (error is TimeoutException) {
error = InteractionTimeoutException(
'Timed out waiting for button press on message ${message.id}',
_nearestCommandContext,
);
}
completer.completeError(error, stackTrace);
}
});
}
ButtonComponentContext context = await completer.future;
context._parent = this;
_delegate = context;
return context;
}