Skip to content
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

Inline keyboard pagination #438

Closed

Conversation

noplanman
Copy link
Member

This PR offers a simple way to add an inline pagination keyboard.

userlist

The idea has been around for a while and #436 gave me the kick to implement it.

How it works
Example command /basicpages
basicpages

BasicpagesCommand.php
In the command, implement the InlineKeyboardPaginator, populate the required static methods, set reply_markup to the paginator, done!

<?php

namespace Longman\TelegramBot\Commands\UserCommands;

use Longman\TelegramBot\Commands\UserCommand;
use Longman\TelegramBot\Entities\InlineKeyboard;
use Longman\TelegramBot\Entities\InlineKeyboardPaginator;
use Longman\TelegramBot\Request;

class BasicpagesCommand extends UserCommand implements InlineKeyboardPaginator
{
    protected $name = 'basicpages';
    protected $description = 'Basic pages for inline keyboard pagination';
    protected $usage = '/basicpages';
    protected $version = '1.0.0';
    protected static $max_pages = 5; // Assigned dynamically in a real-life scenario!

    public static function getCallbackDataId()
    {
        return 'basicpages';
    }

    public static function getPagination($current_page)
    {
        return InlineKeyboard::getPagination(self::getCallbackDataId(), $current_page, self::$max_pages);
    }

    public static function getOutput($current_page)
    {
        return sprintf('Page %d of %d', $current_page, self::$max_pages);
    }

    public function execute()
    {
        // Using pagination
        $data = [
            'chat_id'      => $this->getMessage()->getChat()->getId(),
            'text'         => self::getOutput(1),
            'reply_markup' => self::getPagination(1),
        ];

        return Request::sendMessage($data);
    }
}

CallbackqueryCommand.php
In the callback query handler, we just need to get the current page number and can then edit the message to display the updated data.

<?php

namespace Longman\TelegramBot\Commands\SystemCommands;

use Longman\TelegramBot\Commands\SystemCommand;
use Longman\TelegramBot\Commands\UserCommands\BasicpagesCommand;
use Longman\TelegramBot\Entities\InlineKeyboard;
use Longman\TelegramBot\Request;

class CallbackqueryCommand extends SystemCommand
{
    protected $name = 'callbackquery';
    protected $description = 'Reply to callback query';
    protected $version = '1.0.0';

    public function execute()
    {
        $callback_data = $this->getUpdate()->getCallbackQuery()->getData();

        if (strpos($callback_data, 'basicpages') === 0) {
            return $this->handleBasicPages();
        }

        return Request::emptyResponse();
    }

    protected function handleBasicPages()
    {
        $callback_query = $this->getUpdate()->getCallbackQuery();
        $callback_data  = $callback_query->getData();

        // Get the page from the callback_data.
        $current_page = InlineKeyboard::getPageFromCallbackData($callback_data);

        return Request::editMessageText([
            'chat_id'      => $callback_query->getMessage()->getChat()->getId(),
            'message_id'   => $callback_query->getMessage()->getMessageId(),
            'text'         => BasicpagesCommand::getOutput($current_page),
            'reply_markup' => BasicpagesCommand::getPagination($current_page),
        ]);
    }
}

What would be nice to have changed to make this work even better:

  • Public static properties for commands, so that they can be accessed from everywhere, thus removing the requirement for getCallbackDataId()
  • It would be brilliant to add some kind of registerCallbackQueryHandler method to the default system CallbackqueryCommand class. This could allow adding handlers without having to copy the command and adding it to a custom commands folder.

Thoughts:
The way it is now, when on the first or last page, only 3 buttons get displayed.
first-page
Would it make sense to always display 5 if there are enough pages?
Also, what if there are 100 pages, should there be a second row of buttons for greater page jumps?
big-keyboard

Your opinion!
Please give this a try and give me your feedback!

@noplanman noplanman mentioned this pull request Mar 25, 2017
@jacklul
Copy link
Collaborator

jacklul commented Mar 26, 2017

This is cool!
Will probably make doing stuff like this easier for people!

Some suggestions/ideas:

  • Maybe this could be modified to be a little more 'universal' so user could use alphabetical pagination?

  • Would be nice if we could have few types of button layouts to choose from! Like even simple ones:

2
« »

In that case 'extended button layout':

Also, what if there are 100 pages, should there be a second row of buttons for greater page jumps?

Definitely!

Additional ideas/notes:

  • We could use this pagination with build-in commands: /help /chats etc
  • CallbackqueryCommand could be somehow modified so that other commands could 'register' itself in it so it could redirect to commands based on data (just like in GenericmessageCommand conversation feature) - just prefix data with something like "c11_page1", must be short to fit into 64-character limit

@noplanman
Copy link
Member Author

...so user could use alphabetical pagination?

What exactly do you mean by this? Letters instead of numbers?

button layouts

Brilliant, will see how to make this customisable 👍

We could use this pagination with build-in commands: /help /chats etc

Yep!

CallbackqueryCommand could be somehow modified so that other commands could 'register' itself in it...

Exactly what I meant by registerCallbackQueryHandler, something like this:

CallbackqueryCommand::registerCallbackQueryHandler('pagination_command', 'myCallbackQueryHandler');

function myCallbackQueryHandler($callback_query)
{
    ...
}

@jacklul
Copy link
Collaborator

jacklul commented Mar 26, 2017

...so user could use alphabetical pagination?
What exactly do you mean by this? Letters instead of numbers?

Yeah, sample use: sorting /chats by letters! No idea how hard this will be to achieve though!

@noplanman
Copy link
Member Author

Would be nice if we could have few types of button layouts to choose from! Like even simple ones

Added with 6983b2c, by hiding certain buttons using a blank label.

@noplanman
Copy link
Member Author

noplanman commented Apr 8, 2017

Will close off here, as I'll be moving this whole feature to a separate repo, as an add-on.

Found this neat project that I'll be extending:
https://github.com/lartie/Telegram-Bot-Pagination

@noplanman noplanman closed this Apr 8, 2017
@noplanman
Copy link
Member Author

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants