getButtonPress method

  1. @override
Future<ButtonComponentContext> getButtonPress(
  1. 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:

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;
}