Skip to content

First start at a central paginator system #29

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

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 12 additions & 2 deletions menu/src/main/java/com/jagrosh/jdautilities/menu/ButtonMenu.java
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,17 @@ public void display(Message message)
{
initialize(message.editMessage(getMessage()));
}


@Override
public void displayWithButtons(MessageChannel channel){

}

@Override
public void displayWithReactions(MessageChannel channel){

}

// Initializes the ButtonMenu using a Message RestAction
// This is either through editing a previously existing Message
// OR through sending a new one to a TextChannel.
Expand Down Expand Up @@ -154,7 +164,7 @@ private Message getMessage()
if(text!=null)
mbuilder.append(text);
if(description!=null)
mbuilder.setEmbed(new EmbedBuilder().setColor(color).setDescription(description).build());
mbuilder.setEmbeds(new EmbedBuilder().setColor(color).setDescription(description).build());
return mbuilder.build();
}

Expand Down
247 changes: 51 additions & 196 deletions menu/src/main/java/com/jagrosh/jdautilities/menu/EmbedPaginator.java
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,9 @@
* @author Andre_601
*/
public class EmbedPaginator extends Menu{


private final PaginationHandler paginationHandler;

private final BiFunction<Integer, Integer, String> text;
private final Consumer<Message> finalAction;
private final boolean waitOnSinglePage;
Expand Down Expand Up @@ -74,34 +76,73 @@ protected EmbedPaginator(EventWaiter waiter, Set<User> users, Set<Role> roles, l
this.leftText = leftText;
this.rightText = rightText;
this.allowTextInput = allowTextInput;

this.paginationHandler = new PaginationHandler.Builder(this)
.allowPageWrap(wrapPageEnds)
.allowSinglePage(waitOnSinglePage)
.setBulkSkipLeft(bulkSkipNumber > 1 ? PaginationHandler.EMOJI_BULK_SKIP_LEFT : null)
.setBulkSkipRight(bulkSkipNumber > 1 ? PaginationHandler.EMOJI_BULK_SKIP_RIGHT : null)
.setEmbeds(embeds)
.setFinalAction(finalAction)
.build();
}

/**
* Begins pagination on page 1 as a new {@link net.dv8tion.jda.api.entities.Message Message}
* in the provided {@link net.dv8tion.jda.api.entities.MessageChannel MessageChannel}.
* {@inheritDoc}
*
* @param channel
* The MessageChannel to send the new Message to
*
* @deprecated Deprecated in favour of {@link #displayWithButtons(MessageChannel)} and
* {@link #displayWithReactions(MessageChannel)}.
*/
@Override
@Deprecated
public void display(MessageChannel channel)
{
paginate(channel, 1);
paginationHandler.displayWithReactions(channel, 1);
}

/**
* Begins pagination on page 1 displaying this by editing the provided
* {@link net.dv8tion.jda.api.entities.Message Message}.
* {@inheritDoc}
*
* @param message
* The Message to display the Menu in
*
* @deprecated Deprecated in favour of {@link #displayWithButtons(MessageChannel)} and
* {@link #displayWithReactions(MessageChannel)}.
*/
@Override
@Deprecated
public void display(Message message)
{
paginate(message, 1);
paginationHandler.displayWithReactions(message, 1);
}


/**
* {@inheritDoc}
*
* @param channel
* The {@link net.dv8tion.jda.api.entities.MessageChannel MessageChannel} to display the menu in.
*/
@Override
public void displayWithButtons(MessageChannel channel)
{
paginationHandler.displayWithButtons(channel, 1);
}

/**
* {@inheritDoc}
*
* @param channel
* The {@link net.dv8tion.jda.api.entities.MessageChannel MessageChannel} to display the menu in.
*/
@Override
public void displayWithReactions(MessageChannel channel)
{
paginationHandler.displayWithReactions(channel, 1);
}

/**
* Begins pagination as a new {@link net.dv8tion.jda.api.entities.Message Message}
* in the provided {@link net.dv8tion.jda.api.entities.MessageChannel MessageChannel}, starting
Expand All @@ -114,12 +155,7 @@ public void display(Message message)
*/
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);
paginationHandler.displayWithReactions(channel, pageNum);
}

/**
Expand All @@ -134,188 +170,7 @@ else if(pageNum > embeds.size())
*/
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<Message> action, int pageNum)
{
action.queue(m -> {
if(embeds.size()>1)
{
if(bulkSkipNumber > 1)
m.addReaction(BIG_LEFT).queue();
m.addReaction(LEFT).queue();
m.addReaction(STOP).queue();
if(bulkSkipNumber > 1)
m.addReaction(RIGHT).queue();
m.addReaction(bulkSkipNumber > 1 ? BIG_RIGHT : RIGHT)
.queue(v -> pagination(m, pageNum), t -> pagination(m, pageNum));
}
else if(waitOnSinglePage)
{
m.addReaction(STOP).queue(v -> pagination(m, pageNum), t -> pagination(m, pageNum));
}
else
{
finalAction.accept(m);
}
});
}

private void pagination(Message message, int pageNum)
{
if(allowTextInput || (leftText != null && rightText != null))
paginationWithTextInput(message, pageNum);
else
paginationWithoutTextInput(message, pageNum);
}

private void paginationWithTextInput(Message message, int pageNum)
{
waiter.waitForEvent(GenericMessageEvent.class, event -> {
if(event instanceof MessageReactionAddEvent)
return checkReaction((MessageReactionAddEvent) event, message.getIdLong());
else if(event instanceof MessageReceivedEvent)
{
MessageReceivedEvent mre = (MessageReceivedEvent) event;
if(!mre.getChannel().equals(message.getChannel()))
return false;
String rawContent = mre.getMessage().getContentRaw().trim();
if(leftText != null && rightText != null)
{
if(rawContent.equalsIgnoreCase(leftText) || rawContent.equalsIgnoreCase(rightText))
return isValidUser(mre.getAuthor(), mre.isFromGuild() ? mre.getGuild() : null);
}

if(allowTextInput)
{
try {
int i = Integer.parseInt(rawContent);

if(1 <= i && i <= embeds.size() && i != pageNum)
return isValidUser(mre.getAuthor(), mre.isFromGuild() ? mre.getGuild() : null);
} catch(NumberFormatException ignored) {}
}
}
return false;
}, event -> {
if(event instanceof MessageReactionAddEvent)
{
handleMessageReactionAddAction((MessageReactionAddEvent)event, message, pageNum);
}
else
{
MessageReceivedEvent mre = (MessageReceivedEvent) event;
String rawContent = mre.getMessage().getContentRaw().trim();

int pages = embeds.size();
final int targetPage;

if(leftText != null && rawContent.equalsIgnoreCase(leftText) && (1 < pageNum || wrapPageEnds))
targetPage = pageNum - 1 < 1 && wrapPageEnds ? pages : pageNum - 1;
else if(rightText != null && rawContent.equalsIgnoreCase(rightText) && (pageNum < pages || wrapPageEnds))
targetPage = pageNum + 1 > pages && wrapPageEnds ? 1 : pageNum + 1;
else
targetPage = Integer.parseInt(rawContent);

message.editMessage(renderPage(targetPage)).queue(m -> pagination(m, targetPage));
mre.getMessage().delete().queue(v -> {}, t -> {});
}
}, timeout, unit, () -> finalAction.accept(message));
}

private void paginationWithoutTextInput(Message message, int pageNum)
{
waiter.waitForEvent(MessageReactionAddEvent.class,
event -> checkReaction(event, message.getIdLong()),
event -> handleMessageReactionAddAction(event, message, pageNum),
timeout, unit, () -> finalAction.accept(message));
}

private boolean checkReaction(MessageReactionAddEvent event, long messageId)
{
if(event.getMessageIdLong() != messageId)
return false;
switch(event.getReactionEmote().getName())
{
case LEFT:
case STOP:
case RIGHT:
return isValidUser(event.getUser(), event.isFromGuild() ? event.getGuild() : null);
case BIG_LEFT:
case BIG_RIGHT:
return bulkSkipNumber > 1 && isValidUser(event.getUser(), event.isFromGuild() ? event.getGuild() : null);
default:
return false;
}
}

private void handleMessageReactionAddAction(MessageReactionAddEvent event, Message message, int pageNum)
{
int newPageNum = pageNum;
int pages = embeds.size();
switch(event.getReaction().getReactionEmote().getName())
{
case LEFT:
if(newPageNum == 1 && wrapPageEnds)
newPageNum = pages + 1;
if(newPageNum > 1)
newPageNum--;
break;
case RIGHT:
if(newPageNum == pages && wrapPageEnds)
newPageNum = 0;
if(newPageNum < pages)
newPageNum++;
break;
case BIG_LEFT:
if(newPageNum > 1 || wrapPageEnds)
{
for(int i = 1; (newPageNum > 1 || wrapPageEnds) && i < bulkSkipNumber; i++)
{
if(newPageNum == 1 && wrapPageEnds)
newPageNum = pages + 1;
newPageNum--;
}
}
break;
case BIG_RIGHT:
if(newPageNum < pages || wrapPageEnds)
{
for(int i = 1; (newPageNum < pages || wrapPageEnds) && i < bulkSkipNumber; i++)
{
if(newPageNum == pages && wrapPageEnds)
newPageNum = 0;
newPageNum++;
}
}
break;
case STOP:
finalAction.accept(message);
return;
}

try {
event.getReaction().removeReaction(event.getUser()).queue();
} catch(PermissionException ignored) {}

int n = newPageNum;
message.editMessage(renderPage(newPageNum)).queue(m -> pagination(m, n));
}

private Message renderPage(int pageNum)
{
MessageBuilder mbuilder = new MessageBuilder();
MessageEmbed membed = this.embeds.get(pageNum-1);
mbuilder.setEmbed(membed);
if(text != null)
mbuilder.append(text.apply(pageNum, embeds.size()));
return mbuilder.build();
paginationHandler.displayWithReactions(message, pageNum);
}

/**
Expand Down
Loading