diff --git a/menu/src/main/java/com/jagrosh/jdautilities/menu/ButtonEmbedPaginator.java b/menu/src/main/java/com/jagrosh/jdautilities/menu/ButtonEmbedPaginator.java new file mode 100644 index 00000000..d50a14f9 --- /dev/null +++ b/menu/src/main/java/com/jagrosh/jdautilities/menu/ButtonEmbedPaginator.java @@ -0,0 +1,459 @@ +/* + * Copyright 2016-2018 John Grosh (jagrosh) & Kaidan Gustave (TheMonitorLizard) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.jagrosh.jdautilities.menu; + +import com.jagrosh.jdautilities.commons.waiter.EventWaiter; +import net.dv8tion.jda.api.EmbedBuilder; +import net.dv8tion.jda.api.MessageBuilder; +import net.dv8tion.jda.api.entities.Emoji; +import net.dv8tion.jda.api.entities.Message; +import net.dv8tion.jda.api.entities.MessageChannel; +import net.dv8tion.jda.api.entities.MessageEmbed; +import net.dv8tion.jda.api.entities.Role; +import net.dv8tion.jda.api.entities.User; +import net.dv8tion.jda.api.events.interaction.component.ButtonInteractionEvent; +import net.dv8tion.jda.api.interactions.components.buttons.Button; +import net.dv8tion.jda.api.interactions.components.buttons.ButtonStyle; +import net.dv8tion.jda.api.requests.RestAction; +import net.dv8tion.jda.internal.utils.Checks; +import org.slf4j.LoggerFactory; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.LinkedList; +import java.util.List; +import java.util.Set; +import java.util.concurrent.TimeUnit; +import java.util.function.BiFunction; +import java.util.function.Consumer; + +/** + * A {@link Menu} implementation, nearly identical to {@link EmbedPaginator}, that displays an individual + * {@link MessageEmbed}s on each page instead of a list of text items. + * + *

Unlike Paginator, native Discord buttons are used and allow the user to traverse to the last page + * using the left arrow, the next page using the right arrow, and to stop the EmbedPaginator prematurely + * using the stop button. + */ +public class ButtonEmbedPaginator extends Menu { + private static final List paginators = new ArrayList<>(); + + private final BiFunction text; + private final Consumer finalAction; + private final boolean waitOnSinglePage; + private final List embeds; + private final int bulkSkipNumber; + private final boolean wrapPageEnds; + private final ButtonStyle style; + + public static final Emoji BIG_LEFT = Emoji.fromUnicode("\u23EA"); + public static final Emoji LEFT = Emoji.fromUnicode("\u25C0"); + public static final Emoji STOP = Emoji.fromUnicode("\u23F9"); + public static final Emoji RIGHT = Emoji.fromUnicode("\u25B6"); + public static final Emoji BIG_RIGHT = Emoji.fromUnicode("\u23E9"); + + protected ButtonEmbedPaginator(EventWaiter waiter, Set users, Set roles, long timeout, TimeUnit unit, + BiFunction text, Consumer finalAction, + boolean waitOnSinglePage, List embeds, int bulkSkipNumber, + boolean wrapPageEnds, ButtonStyle style) { + super(waiter, users, roles, timeout, unit); + this.text = text; + this.finalAction = finalAction; + this.waitOnSinglePage = waitOnSinglePage; + this.embeds = embeds; + this.bulkSkipNumber = bulkSkipNumber; + this.wrapPageEnds = wrapPageEnds; + this.style = style; + } + + /** + * Begins pagination on page 1 as a new {@link Message} in the provided {@link MessageChannel}. + * + * @param channel The MessageChannel to send the new Message to + */ + @Override + public void display(MessageChannel channel) { + paginate(channel, 1); + } + + /** + * Begins pagination on page 1 displaying this by editing the provided {@link Message}. + * + * @param message The Message to display the Menu in + */ + @Override + public void display(Message message) { + paginate(message, 1); + } + + /** + * Begins pagination as a new {@link Message} in the provided {@link MessageChannel}, starting on whatever + * page number is provided. + * + * @param channel The MessageChannel to send the new Message to + * @param pageNum The page number to begin on + */ + public void paginate(MessageChannel channel, int pageNum) { + if (pageNum < 1) + pageNum = 1; + else if (pageNum > embeds.size()) + pageNum = embeds.size(); + Message msg = renderPage(pageNum); + initialize(channel.sendMessage(msg), pageNum); + } + + /** + * Begins pagination displaying this by editing the provided {@link Message}, starting on whatever page number + * is provided. + * + * @param message The message to edit + * @param pageNum The page number to begin on + */ + public void paginate(Message message, int pageNum) { + if (pageNum < 1) + pageNum = 1; + else if (pageNum > embeds.size()) + pageNum = embeds.size(); + Message msg = renderPage(pageNum); + initialize(message.editMessage(msg), pageNum); + } + + private void initialize(RestAction action, int pageNum) { + action.queue(m -> { + if (embeds.size() > 1) { + List