Search code examples
telegram-bottelegraf.js

How to change the width of inline buttons to chat width, instead of message width


I've seen a bot that has inline buttons across the whole chat area, not dependant on the button's text width):

enter image description here

For some reason my buttons are drawn differently, and the text inside the buttons gets trimmed.

enter image description here

I don't see a parameter I can pass to change the width, and google searches say that it's impossible to change it for now, so - how come the buttons on the first screenshot are full width? What am I missing here? Thanks.

edit:

sample code to send a message with inline keyboard that I use & try to figure out the button width logic:

  await ctx.telegram.sendMessage(
    ctx.chat?.id!,
    `Sample text bla bla bla bla bla bla`,
    {
      parse_mode: 'HTML',
      reply_markup: {
        inline_keyboard: [
          [Markup.button.callback('Sample button with emoji \u{1F604}', `back`)]
        ]
      }
    }
  )
  
  await ctx.telegram.sendMessage(
    ctx.chat?.id!,
    `Sample text bla bla bla bla bla`,
    {
      parse_mode: 'HTML',
      reply_markup: {
        inline_keyboard: [
          [Markup.button.callback('Sample button with emoji \u{1F604}', `back`)]
        ]
      }
    }
  )

enter image description here

Android phone view:

enter image description here


Solution

  • Maybe here invisible spaces are used. Cause the bot automatically cuts these spaces you should use special symbol "&#x200D;" right after spaces. And remember, in order this to work you have to use parse_mode "HTML" and put the text in frames of <pre></pre>.

    Edit:

    Since it is the text that determines the width of the inline keyboard, to give it the correct width, use this function to format the text so that it is always the same length, and hence the inline keyboard:

    function formatTextToEqualBlockWidth(string) {
    
    
      // Special zero-width connector in hex format that doesn't cut off the bot:
    
      const nullSeparator = '&#x200D;';
    
    
      // The maximum number of characters, upon reaching the number of which the bot starts to stretch the width of the block with buttons:
    
      const maxNumberOfSymbol = 29;
    
    
      // Pad the right side of each new line with spaces and a special character, thanks to which the bot does not cut off these spaces, and then add them to the array:
    
      let resultStringArray = [];
    
      while (string.length) {
    
    
        // Get a substring with the length of the maximum possible width of the option block:
    
        let partOfString = string.substring(0, maxNumberOfSymbol).trim();
    
    
        // Find the first space on the left of the substring to pad with spaces and a line break character:
    
        let positionOfCarriageTransfer = string.length < maxNumberOfSymbol ? string.length : partOfString.lastIndexOf(' ');
        positionOfCarriageTransfer = positionOfCarriageTransfer == -1 ? partOfString.length : positionOfCarriageTransfer;
    
    
        // Pad the substring with spaces and a line break character at the end:
    
        partOfString = partOfString.substring(0, positionOfCarriageTransfer)
    
        partOfString = partOfString + new Array(maxNumberOfSymbol - partOfString.length).join(' ') + nullSeparator;
    
    
        // Add to array of strings:
    
        resultStringArray.push(`<pre>${partOfString}</pre>`);
    
    
        // Leave only the unprocessed part of the string:
    
        string = string.substring(positionOfCarriageTransfer).trim();
      }
    
    
      // Send a formatted string as a column equal to the maximum width of the message that the bot does not deform:
    
      return resultStringArray.join('\n');
    }
    
    
    let textMessage = formatTextToEqualBlockWidth('Lorem Ipsum is simply dummy text of the printing and typesetting industry. ')
    
    sendMenuKeyboardMessageToUser(
      '1572394019',
      textMessage,
      {
        inline_keyboard: [
          [
            { text: 'Test1', callback_data: 'TestId' }
          ]
        ]
      },
      'HTML'
    );
    
    
    textMessage = formatTextToEqualBlockWidth('It is a long established fact that a reader ')
    
    sendMenuKeyboardMessageToUser(
      '1572394019',
      textMessage,
      {
        inline_keyboard: [
          [
            { text: 'Test2', callback_data: 'TestId2' }
          ]
        ]
      },
      'HTML'
    );
    
    
    textMessage = formatTextToEqualBlockWidth('It is test')
    
    sendMenuKeyboardMessageToUser(
      '1572394019',
      textMessage,
      {
        inline_keyboard: [
          [
            { text: 'Test2', callback_data: 'TestId2' }
          ]
        ]
      },
      'HTML'
    );
    
    

    Example