All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.freya02.botcommands.api.pagination.paginator.BasicPaginator Maven / Gradle / Ivy

package com.freya02.botcommands.api.pagination.paginator;

import com.freya02.botcommands.api.Logging;
import com.freya02.botcommands.api.components.Components;
import com.freya02.botcommands.api.components.data.InteractionConstraints;
import com.freya02.botcommands.api.components.event.ButtonEvent;
import com.freya02.botcommands.api.pagination.BasicPagination;
import com.freya02.botcommands.api.pagination.PaginatorSupplier;
import com.freya02.botcommands.api.pagination.TimeoutInfo;
import com.freya02.botcommands.api.utils.ButtonContent;
import net.dv8tion.jda.api.entities.Message;
import net.dv8tion.jda.api.entities.MessageEmbed;
import net.dv8tion.jda.api.interactions.components.ActionRow;
import net.dv8tion.jda.api.interactions.components.buttons.Button;
import net.dv8tion.jda.api.interactions.components.buttons.ButtonStyle;
import net.dv8tion.jda.api.utils.messages.MessageEditData;
import net.dv8tion.jda.internal.utils.Checks;
import org.jetbrains.annotations.NotNull;
import org.slf4j.Logger;

import java.util.List;

/**
 * @param  Type of the implementor
 */
@SuppressWarnings("unchecked")
public abstract class BasicPaginator> extends BasicPagination {
	private static final Logger LOGGER = Logging.getLogger();
	private static final MessageEditData DELETED_MESSAGE = MessageEditData.fromContent("[deleted]");
	protected final PaginatorSupplier supplier;
	private final Button deleteButton;
	protected int maxPages;
	protected int page = 0;
	private Button firstButton, previousButton, nextButton, lastButton;

	protected BasicPaginator(@NotNull Components componentsService,
							 InteractionConstraints constraints, TimeoutInfo timeout, int _maxPages, PaginatorSupplier supplier, boolean hasDeleteButton,
							 ButtonContent firstContent, ButtonContent previousContent, ButtonContent nextContent, ButtonContent lastContent, ButtonContent deleteContent) {
		super(componentsService, constraints, timeout);

		this.maxPages = _maxPages;
		this.supplier = supplier;

		firstButton = this.componentsService.ephemeralButton(ButtonStyle.PRIMARY, firstContent, builder -> {
			builder.bindTo(e -> {
				page = 0;

				e.editMessage(get()).queue();
			});
			builder.setConstraints(constraints);
		});

		previousButton = this.componentsService.ephemeralButton(ButtonStyle.PRIMARY, previousContent, builder -> {
			builder.bindTo(e -> {
				page = Math.max(0, page - 1);

				e.editMessage(get()).queue();
			});
			builder.setConstraints(constraints);
		});

		nextButton = this.componentsService.ephemeralButton(ButtonStyle.PRIMARY, nextContent, builder -> {
			builder.bindTo(e -> {
				page = Math.min(maxPages - 1, page + 1);

				e.editMessage(get()).queue();
			});
			builder.setConstraints(constraints);
		});

		lastButton = this.componentsService.ephemeralButton(ButtonStyle.PRIMARY, lastContent, builder -> {
			builder.bindTo(e -> {
				page = maxPages - 1;

				e.editMessage(get()).queue();
			});
			builder.setConstraints(constraints);
		});

		if (hasDeleteButton) {
			//Unique use in the case the message isn't ephemeral
			this.deleteButton = this.componentsService.ephemeralButton(ButtonStyle.DANGER, deleteContent, builder -> {
				builder.bindTo(this::onDeleteClicked);
				builder.setConstraints(constraints);
				builder.setOneUse(true);
			});
		} else {
			this.deleteButton = null;
		}
	}

	public int getMaxPages() {
		return maxPages;
	}

	public int getPage() {
		return page;
	}

	/**
	 * Sets the page number, this does not update the embed in any way,
	 * you can use {@link #get()} with an editOriginal in order to update the embed on Discord
	 *
	 * @param page Number of the page, from 0 to maxPages - 1
	 * @return This instance for chaining convenience
	 */
	public T setPage(int page) {
		Checks.check(page >= 0, "Page cannot be negative");
		Checks.check(page < maxPages, "Page cannot be higher than max page (%d)", maxPages);

		this.page = page;

		return (T) this;
	}

	protected void setMaxPages(int maxPages) {
		this.maxPages = maxPages;
	}

	private void onDeleteClicked(ButtonEvent e) {
		cancelTimeout();

		if (!e.getMessage().isEphemeral()) {
			e.deferEdit().queue();
			e.getMessage().delete().queue();
		} else {
			e.editMessage(DELETED_MESSAGE).queue();

			LOGGER.warn("Attempted to delete a ephemeral message using a Paginator delete button, consider disabling the delete button in the constructor or making your message not ephemeral, pagination supplier comes from {}", supplier.getClass().getName());
		}

		cleanup();
	}

	/**
	 * Returns the current page as a Message, you only need to use this once to send the initial embed. 
* The user can then use the navigation buttons to navigate. * * @return The {@link Message} for this Paginator */ @Override public MessageEditData get() { onPreGet(); putComponents(); final MessageEmbed embed = getEmbed(); messageBuilder.setEmbeds(embed); final List rows = components.getActionRows(); messageBuilder.setComponents(rows); onPostGet(); return messageBuilder.build(); } @NotNull protected MessageEmbed getEmbed() { return supplier.get((T) this, messageBuilder, components, page); } protected void putComponents() { if (page == 0) { previousButton = previousButton.asDisabled(); firstButton = firstButton.asDisabled(); } else { previousButton = previousButton.asEnabled(); firstButton = firstButton.asEnabled(); } if (page >= maxPages - 1) { nextButton = nextButton.asDisabled(); lastButton = lastButton.asDisabled(); } else { nextButton = nextButton.asEnabled(); lastButton = lastButton.asEnabled(); } if (deleteButton != null) { components.addComponents( firstButton, previousButton, nextButton, lastButton, deleteButton ); } else { components.addComponents( firstButton, previousButton, nextButton, lastButton ); } } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy