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

feat: keyboard button builders #420

Merged
merged 33 commits into from
Jun 25, 2023
Merged

feat: keyboard button builders #420

merged 33 commits into from
Jun 25, 2023

Conversation

KnorpelSenf
Copy link
Member

@KnorpelSenf KnorpelSenf commented May 31, 2023

Adds keyboard button builders.

  • static method to create buttons from labels via Keyboard.text("label")
  • static method to create keyboards from buttons via Keyboard.from(array)
  • static method to create keyboards from labels via Keyboard.from(stringArray)
  • instance method to clone keyboards via keyboard.clone()
  • instance method to append keyboards via keyboard.append(other0, other1, other2)
  • instance method to transpose rows and columns via keyboard.toTransposed()
  • instance method to reflow buttons via keyboard.toWrapped()

The same works for inline keyboards.

Closes #104.

@KnorpelSenf KnorpelSenf requested a review from Loskir May 31, 2023 13:28
@Loskir
Copy link
Contributor

Loskir commented May 31, 2023

Some nitpicks:

  1. I can't see why an option to specify the maximum number of buttons in the first row in reflow is particularly useful. Are there any use-cases?
  2. I don't think reflow should be an in-place method. It should rather be a static method receiving a 1-d array of buttons. Maybe name it chunk as well
  3. I see that it follows a common theme, but it annoys me so much that transpose is an in-place method.
  4. Is fromColumns any useful? Seems like a very specific method too.

@Loskir
Copy link
Contributor

Loskir commented May 31, 2023

Maybe add prepend as well?

@Loskir
Copy link
Contributor

Loskir commented May 31, 2023

Maybe add addRow as an alias for row? So that

const keyboard = new Keyboard()
keyboard.addRow(....)

sounds more natural

@KnorpelSenf
Copy link
Member Author

  1. I can't see why an option to specify the maximum number of buttons in the first row in reflow is particularly useful. Are there any use-cases?

Yes. By default, the last row will be half. By allowing the number of buttons on the first row to be specified, we can make the first row half. For 10 items, we can do Keyboard.from(array).reflow(3, { first: array.length % 3 }) which will give us

[  0  ]
[1 2 3]
[4 5 6]
[7 8 9]

rather than

[0 1 2]
[3 4 5]
[6 7 8]
[  9  ]
  1. I don't think reflow should be an in-place method. It should rather be a static method receiving a 1-d array of buttons. Maybe name it chunk as well

I added clone for these cases so one can do keyboard.clone().reflow() if in-place is a problem. How about we remove clone and always return copies of the current keyboard? I see no benefit of static methods here.

I expected Keyboard.from(data).reflow() to be the most common use case, hence in-place made sense.

  1. I see that it follows a common theme, but it annoys me so much that transpose is an in-place method.

Same.

  1. Is fromColumns any useful? Seems like a very specific method too.

It's useful if you want to map an array of strings to a list of buttons that all are places in a single column. I encouter this quite often with Keyboard.fromColumns(["Welcome", "Settings", "About"]). Not providing this method either requires an explicit transpose call or a .map(x => [x]).

@KnorpelSenf
Copy link
Member Author

Maybe add prepend as well?

I see no benefit, just flip the two values?

By the way, should this return a copy, too? In other words, should we create concat rather than append?

@KnorpelSenf
Copy link
Member Author

Maybe add addRow as an alias for row?

What is the benefit of redundancy?

@Loskir
Copy link
Contributor

Loskir commented May 31, 2023

Maybe add addRow as an alias for row?

What is the benefit of redundancy?

just like you added fromRows that is the same as from.

The use cases are shifting from chaining new Keyboard().text().row() to separate calls

const keyboard = Keyboard.from(initialData)
if (something) {
  keyboard.row(someConditionalData)
}

If this was new code, it would make a lot more sense to call it addRow instead of row. So why not add it to make such code more readable?

@Loskir
Copy link
Contributor

Loskir commented May 31, 2023

Maybe add prepend as well?

I see no benefit, just flip the two values?

You're right, prepend is not that useful and it would also lead to worse code in general.

@Loskir
Copy link
Contributor

Loskir commented May 31, 2023

Forget about addRow, I just realized it accepts row(button, button, button) not row([button, button, button])

@Loskir
Copy link
Contributor

Loskir commented May 31, 2023

One use case that I'm thinking about rn is conditional buttons, e.g.

const keyboard = Keyboard.from([[button]])
if (userLoggedIn) {
  keyboard.append([[Keyboard.text('Profile')]])
}

append seems like a great option for this. But for this to work it should accept not only Keyboards, but also Button[][]
Or maybe you have other ideas? We are not limited by existing methods here

@KnorpelSenf
Copy link
Member Author

Maybe add addRow as an alias for row?

What is the benefit of redundancy?

just like you added fromRows that is the same as from.

The use cases are shifting from chaining new Keyboard().text().row() to separate calls

const keyboard = Keyboard.from(initialData)
if (something) {
  keyboard.row(someConditionalData)
}

If this was new code, it would make a lot more sense to call it addRow instead of row. So why not add it to make such code more readable?

I don't see the pattern that you're referring to. That sounds like you also want to rename it to keyboard.addText("") and keyboard.addRequestLocation("") and so on?

@KnorpelSenf
Copy link
Member Author

Forget about addRow, I just realized it accepts row(button, button, button) not row([button, button, button])

Oh okay

@KnorpelSenf
Copy link
Member Author

One use case that I'm thinking about rn is conditional buttons, e.g.

const keyboard = Keyboard.from([[button]])
if (userLoggedIn) {
  keyboard.append([[Keyboard.text('Profile')]])
}

append seems like a great option for this. But for this to work it should accept not only Keyboards, but also Button[][] Or maybe you have other ideas? We are not limited by existing methods here

We could make it accept both Keyboard instances as well as anything else that Keyboard.from accepts. That would cover this use case, and it would be simple to implement. What do you think?

@Loskir
Copy link
Contributor

Loskir commented May 31, 2023

Great idea! We could make Keyboard.from(new Keyboard()) a noop and then wrap anything passed in Keyboard.from

@KnorpelSenf
Copy link
Member Author

Nice! Will do

@Loskir
Copy link
Contributor

Loskir commented May 31, 2023

Speaking of reflow and fromColumn, how about this?

const keyboard = Keyboard.chunk([a, b, c], 1) // [[a], [b], [c]]

const keyboard = Keyboard.chunkReverse([a, b, c, d, e], 3) // [[a, b], [c, d, e]]

src/convenience/keyboard.ts Outdated Show resolved Hide resolved
@KnorpelSenf
Copy link
Member Author

Speaking of reflow and fromColumn, how about this?

Those are just array helper methods, right? So they don't really create keyboards

@Loskir
Copy link
Contributor

Loskir commented May 31, 2023

Those are just array helper methods, right? So they don't really create keyboards

Maybe they do the transformation and then pass the result to Keyboard.from

@codecov
Copy link

codecov bot commented May 31, 2023

Codecov Report

Patch coverage: 100.00% and project coverage change: +2.67 🎉

Comparison is base (0e7dbee) 38.67% compared to head (5f30bc9) 41.35%.

Additional details and impacted files
@@            Coverage Diff             @@
##             main     #420      +/-   ##
==========================================
+ Coverage   38.67%   41.35%   +2.67%     
==========================================
  Files          16       16              
  Lines        4815     5035     +220     
  Branches      194      204      +10     
==========================================
+ Hits         1862     2082     +220     
  Misses       2951     2951              
  Partials        2        2              
Impacted Files Coverage Δ
src/composer.ts 97.37% <ø> (ø)
src/convenience/keyboard.ts 100.00% <100.00%> (ø)

☔ View full report in Codecov by Sentry.
📢 Do you have feedback about the report comment? Let us know in this issue.

@KnorpelSenf
Copy link
Member Author

@KnorpelSenf KnorpelSenf mentioned this pull request Jun 18, 2023
7 tasks
src/convenience/keyboard.ts Outdated Show resolved Hide resolved
[["a", "c", "d"], ["b", "e"], ["f"]],
);
const keyboard = Keyboard.from([["a", "b", "c"], ["d", "e"], ["f"]]);
assertEquals(keyboard.toTransposed().toTransposed(), keyboard);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is begging for a property-based test.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't do those yet. We can consider adding new test setups in future PQs.

test/convenience/keyboard.test.ts Show resolved Hide resolved
deno.jsonc Show resolved Hide resolved
src/convenience/keyboard.ts Outdated Show resolved Hide resolved
src/convenience/keyboard.ts Show resolved Hide resolved
src/convenience/keyboard.ts Outdated Show resolved Hide resolved
src/convenience/keyboard.ts Outdated Show resolved Hide resolved
@KnorpelSenf KnorpelSenf requested a review from Loskir June 25, 2023 11:16
@KnorpelSenf KnorpelSenf dismissed EdJoPaTo’s stale review June 25, 2023 21:12

The changes have been addressed

Copy link
Contributor

@Loskir Loskir left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM 🎉

@KnorpelSenf KnorpelSenf merged commit b0fcaa1 into main Jun 25, 2023
8 checks passed
@KnorpelSenf KnorpelSenf deleted the keyboard-from branch June 25, 2023 22:25
KnorpelSenf added a commit to ssistoza/grammY that referenced this pull request Jun 25, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
Status: Done
Coding
In progress
Development

Successfully merging this pull request may close these issues.

feat: Keyboard button builders and Keyboard.from
6 participants