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

Added username completion in channels #93

Merged

Conversation

Tangdongle
Copy link

This adds nickname auto-completion for channels.

When we instantiate the text_input from the Channel's view with a list of users in that channel.

From there, we need to differentiate between a /command and a user completion, so we add a CompletionType to each Completion Entry. /commands only auto-complete from the start of the input text, whereas name completion can occur from any word.

Finally, we replace the current word being completed without sending, so the user can continue to type.

@Tangdongle Tangdongle mentioned this pull request Jul 4, 2023
Comment on lines 243 to 97
pub fn process(&mut self, input: &str, users: Vec<User>) {
self.with_users(users);
let maybe_command = input.starts_with('/');
let Some((head, rest)) = Self::valid_completion_input(input, maybe_command) else {
self.reset();
return;
Copy link
Member

Choose a reason for hiding this comment

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

Let's add some better separation between processing for a command vs user completion. If input starts with a slash, we can branch into a process_command function, otherwise process_user.

Then we only need to add the users info inside process_user compared to us always adding it here

src/widget/input.rs Outdated Show resolved Hide resolved
@Tangdongle
Copy link
Author

Awesome, thanks for the feedback, I'll have a look at these today

@Tangdongle Tangdongle force-pushed the add_username_completion branch 3 times, most recently from d8a421e to c868590 Compare July 5, 2023 08:33
@tarkah
Copy link
Member

tarkah commented Jul 5, 2023

@Tangdongle It's looking good! I've pushed a few commits to get it over the finish line, let me know what you think.

  • I've cleaned up some of the types to eliminate some impossible states and streamline some things
  • User completions are now only triggered if @ is typed. This is because normal typing becomes extremely annoying when the completions list is constantly popping up for any letter. I'm open to suggestions on better alternatives to trigger user completions, but this feels fairly standard.
  • I've limited the completion popup to a sliding window of 5 entries. Since many user entries can show up, the popup sometimes would get way too long. Tabbing shifts this window as expected.

@Tangdongle
Copy link
Author

@tarkah Legendary! Thanks for cleaning that up, hope it wasn't too much of a hassle!

Yeah, I see what you've done here, looks much cleaner. I've taken it for a spin and it looks good to me!

@tarkah
Copy link
Member

tarkah commented Jul 6, 2023

Awesome! Not at all, you put it in a really nice spot so it all came together nicely 👌

I'm going to hold off on merging until @casperstorm can test. I'm not sure I love @ as the trigger in IRC so I want his feedback on the best UX for this.

@@ -51,6 +52,7 @@ pub enum Event {
pub struct Input<'a, Message> {
id: Id,
buffer: Buffer,
users: Vec<User>,
Copy link
Contributor

Choose a reason for hiding this comment

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

Could this borrow a slice to avoid the clone in view?

Suggested change
users: Vec<User>,
users: &'a [User],

Copy link
Member

Choose a reason for hiding this comment

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

Unfortunately not. We're currently depending on the IRC crate for managing the user list per channel and it doesn't expose a way to get a reference to this data.

Ideally we manage channels and users ourselves so we could make this optimization. It'd definitely benefit us in the long run as we have better control over our data.

Copy link
Member

@tarkah tarkah Jul 6, 2023

Choose a reason for hiding this comment

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

A middle ground solution would be to extract channel and user lists after receiving each batch of IRC messages which can be stored in Connection. This will ensure they're in sync but give us this level of control.

Copy link
Contributor

Choose a reason for hiding this comment

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

Yup, just took a look at the irc crate. A bit unfortunate it relies heavily on interior mutation :/

Copy link
Member

@tarkah tarkah Jul 6, 2023

Choose a reason for hiding this comment

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

I've created a tracking issue for this here:

#102

Copy link
Member

Choose a reason for hiding this comment

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

Fixed in 3a54355 after rebasing to #104

@casperstorm
Copy link
Member

I'm going to hold off on merging until @casperstorm can test. I'm not sure I love @ as the trigger in IRC so I want his feedback on the best UX for this.

I think we need to rethink the UX slightly, it not that irc idiomatic. The core functionality however is spot on.
Reason its nice to have completions list for / commands is that it also serves as a simple documentation for users. IRC commands can be a little awkward to remember. However, for highlighting a nick I don't think we need a completions list since you already know what (who) you are looking for, as soon as you start writing.

Because of this, the most common practise is to be able to trigger at all times when pressing Tab (without any prefix). This also means that we save a few clicks. Currently in this PR if i want to highlight tarkah I would do:

  1. @
  2. ta
  3. Tab
  4. Enter

My suggestion would be a system where when pressing Tab we try to match a nick, and pressing Tab again cycles, without displaying our completion list. Take the following scenario as an example: We have a irc channel with three users: [tarkah, tarsnap, casper].
Starting with a empty prompt:

  1. hiSpace
    a. prompt: [hi ]
  2. t
    a. prompt: [hi t]
  3. tab
    a. prompt: [hi tarkah]
  4. tab
    a. prompt: [hi tarsnap]

@Tangdongle
Copy link
Author

Ok, I got a little something going on, lemme know what you think. Seems to work well enough from my tests (i.e. "it works on my machine").

did notice that if you have text in the input buffer and then open a new channel, the text carries across to the newly opened channels buffer. Doesn't seem related to the change, so I'll raise a bug for it.

@tarkah
Copy link
Member

tarkah commented Jul 6, 2023

@Tangdongle I ended up pushing a larger refactor since the previous implementation didn't really jive with the new requirements and we were introducing a lot of impossible states.

The new implementation separates user / command completion logic and should be much simpler to follow. We also can get user completions while showing the command popup for the selected command! Great for /msg and the like :D

Thanks so much for tackling this, it was a huge help!

@tarkah tarkah force-pushed the add_username_completion branch 2 times, most recently from 5b58711 to d2ca1c5 Compare July 6, 2023 15:35
@tarkah tarkah changed the base branch from main to feat/optimize-channel-lists July 6, 2023 17:20
Copy link
Member

@casperstorm casperstorm left a comment

Choose a reason for hiding this comment

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

This is SUCH a great feature.
Thanks for the work @Tangdongle and @tarkah.

Comment on lines 306 to 307
let nickname = user.nickname();
nickname
Copy link
Member

Choose a reason for hiding this comment

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

A tiny thing could be that we lower-cased both rest and nickname so we can tab-complete from t to Tarkah.

Not blocking but just an idea.

Copy link
Member

Choose a reason for hiding this comment

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

Good idea! 09c9e78

}
}

static COMMAND_LIST: Lazy<Vec<Command>> = Lazy::new(|| {
Copy link
Member

Choose a reason for hiding this comment

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

I like this 👍🏻
Perhaps some macro magic in the future.

CHANGELOG.md Outdated Show resolved Hide resolved
tarkah and others added 2 commits July 6, 2023 10:53
Co-authored-by: Casper Rogild Storm <casper+github@rogildstorm.com>
@tarkah tarkah merged commit b705237 into squidowl:feat/optimize-channel-lists Jul 6, 2023
1 check passed
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.

4 participants