getMultiSelection<T> method
- List<
T> choices, - MessageBuilder builder,
- {ResponseLevel? level,
- Duration? timeout,
- bool authorOnly = true,
- FutureOr<
SelectMenuOptionBuilder> toSelectMenuOption(- T
- Converter<
T> ? converterOverride}
inherited
Present the user with a drop-down menu of choices and return the selected choices.
If timeout
is set, this method will complete with an error after timeout
has passed.
If authorOnly
is set, only the author of this interaction will be able to interact with a
button.
level
will change the level at which the message is sent, similarly to respond.
converterOverride
can be set to change how each value is converted to a multi-select option.
The default is to use Converter.toSelectMenuOption on the default converter for T
.
You might also be interested in:
- getSelection, for getting a single selection;
- getButtonSelection, for getting a selection from a button;
- awaitSelection, for getting a selection from a pre-existing selection menu.
Implementation
@override
Future<List<T>> getMultiSelection<T>(
List<T> choices,
MessageBuilder builder, {
ResponseLevel? level,
Duration? timeout,
bool authorOnly = true,
FutureOr<SelectMenuOptionBuilder> Function(T)? toSelectMenuOption,
Converter<T>? converterOverride,
}) async {
if (_delegate != null) {
return _delegate!.getMultiSelection(
choices,
builder,
authorOnly: authorOnly,
converterOverride: converterOverride,
level: level,
timeout: timeout,
toSelectMenuOption: toSelectMenuOption,
);
}
toSelectMenuOption ??= converterOverride?.toSelectMenuOption;
toSelectMenuOption ??= commands.getConverter(RuntimeType<T>())?.toSelectMenuOption;
if (toSelectMenuOption == null) {
throw UncaughtCommandsException(
'No suitable method for converting $T to SelectMenuOptionBuilder found',
_nearestCommandContext,
);
}
Map<String, T> idToValue = {};
List<SelectMenuOptionBuilder> options = await Future.wait(choices.map(
(value) async {
SelectMenuOptionBuilder builder = await toSelectMenuOption!(value);
idToValue[builder.value] = value;
return builder;
},
));
ComponentId menuId = ComponentId.generate(
expirationTime: timeout,
allowedUser: authorOnly ? user.id : null,
);
SelectMenuBuilder menu = SelectMenuBuilder(
type: MessageComponentType.stringSelect,
customId: menuId.toString(),
options: options,
maxValues: choices.length,
);
ActionRowBuilder row = ActionRowBuilder(components: [menu]);
(builder.components ??= []).add(row);
Message message = await respond(builder, level: level);
try {
SelectMenuContext<List<String>> context =
await commands.eventManager.nextSelectMenuEvent(menuId);
context._parent = this;
_delegate = context;
for (final value in context.selected) {
final matchingOptionIndex = menu.options!.indexWhere((option) => option.value == value);
if (matchingOptionIndex >= 0) {
menu.options![matchingOptionIndex] = SelectMenuOptionBuilder(
label: menu.options![matchingOptionIndex].label,
value: value,
);
}
}
return context.selected.map((id) => idToValue[id]!).toList();
} on TimeoutException catch (e, s) {
throw InteractionTimeoutException(
'TImed out waiting for selection',
_nearestCommandContext,
)..stackTrace = s;
} finally {
menu.isDisabled = true;
await _updateMessage(this, message, MessageCreateUpdateBuilder.fromMessageBuilder(builder));
}
}