EdJoPaTo / grammy-inline-menu

Inline Menus for Telegram made simple. Successor of telegraf-inline-menu.
MIT License
357 stars 44 forks source link

pagination docs #73

Closed asvaata closed 4 years ago

asvaata commented 4 years ago

Hello

I find “pagination” documentation a bit limited. I don’t understand how it works and with what it does interact. I have the following error representation

menu.select('error', errors.map(o => o.callback_name), {
  textFunc: (ctx, key) => errors.filter(o => o.callback_name === key)[0].error_name,
  setFunc: async (ctx, key) => ctx.reply(errors.filter(o => o.callback_name === key)[0].answer),
  columns: 1,
  maxRows: 3
})

Also this is “pagination” code

menu.pagination('page', {
  setPage: () => 1,
  getTotalPages: () => 2,
  getCurrentPage: () => 3
})

I can’t find ways to connect them. Help me please.

EdJoPaTo commented 4 years ago

The idea of pagination is to show only partial content in the message text. Small example, you have a very long todo list with things you want to do and want to show them in a limited length message (4096 is the current limit of telegram messages if I remember correctly). You can for example show 1 per page. Thats a use case where pagination helps.

The basic is to have a page number which content should be showed. This is saved by you. In the example its saved within the session. When the user selects a new page setPage is called. You can then update the stored information. When the menu is updated it needs to know how many pages are there and which is the current one. This is handled with getCurrentPage and getTotalPages. As you are in charge of the stored information you can use it the way you like in the menu text.

function menuText(ctx) {
  const page = ctx.session.page
  const todoListEntries = ctx.session.todoList
  const entriesToShow = todoListEntries.slice(page, page + 1)

  return entriesToShow.join('\n\n')
}

const menu = new TelegrafInlineMenu(menuText)
menu.pagination('page', {
  setPage: (ctx, page) => {
    ctx.session.page = page
  },
  getCurrentPage: ctx => ctx.session.page,
  getTotalPages: ctx => ctx.session.todoList.length
})

I hope it helps :)

asvaata commented 4 years ago

@EdJoPaTo Either I didn’t understand you, or you are me, I want something like this. Is it possible to do this with your framework? p.s Sorry for my English :D

ezgif com-crop

EdJoPaTo commented 4 years ago

Thats also possible with menu.pagination as you can do whatever you like with the page information. You store it and you handle it.

menu.select and menu.selectSubmenu also have their own pagination which simplifies what you want to accomplish.

const menu = new TelegrafInlineMenu('some text')
menu.select('selection', ['a', 'b', 'c', 'd', …], {
  columns: 1,
  maxRows: 3,
  getCurrentPage: ctx => ctx.session.page,
  setPage: (ctx, page) => {
    ctx.session.page = page
  }
}
asvaata commented 4 years ago

Thank you very much, it helped me. sorry for being stupid