Skip to content

Commit d7748ed

Browse files
committed
stabilize and dedup autocomplete users, increase 10 -> 25 online user autocomplete
1 parent 797cc39 commit d7748ed

1 file changed

Lines changed: 50 additions & 16 deletions

File tree

src/discord/commands/util.rs

Lines changed: 50 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use std::{cmp::Reverse, sync::Arc, time::Duration};
1+
use std::{sync::Arc, time::Duration};
22

33
use fuzzy_matcher::{FuzzyMatcher, skim::SkimMatcherV2};
44
use itertools::Itertools;
@@ -142,28 +142,62 @@ fn wrap_user_autocomplete<'a>(
142142
query: &str,
143143
iter: impl Iterator<Item = (&'a str, i32)>,
144144
) -> Vec<AutocompleteChoice> {
145-
iter.sorted_by_key(|(username, id)| {
146-
if let Ok(query_id) = query.parse::<i32>() {
147-
if *id == query_id {
148-
return Reverse(i64::MAX); // highest priority if ID matches
145+
let query_id = query.parse::<i32>().ok();
146+
147+
let mut choices = iter
148+
.sorted_by(|a, b| {
149+
let (a_name, a_id) = a;
150+
let (b_name, b_id) = b;
151+
152+
let mut a_score = 0;
153+
let mut b_score = 0;
154+
155+
if let Some(qid) = query_id {
156+
if *a_id == qid {
157+
a_score = i64::MAX - 1;
158+
}
159+
if *b_id == qid {
160+
b_score = i64::MAX - 1;
161+
}
149162
}
150-
}
151163

152-
if username.eq_ignore_ascii_case(query) {
153-
return Reverse(i64::MAX - 1); // second highest priority if username matches
154-
}
164+
// check for exact username match
165+
if a_name.eq_ignore_ascii_case(query) {
166+
a_score = i64::MAX - 2;
167+
}
168+
if b_name.eq_ignore_ascii_case(query) {
169+
b_score = i64::MAX - 2;
170+
}
155171

156-
// fuzzy match on username
157-
Reverse(fuzzy_match(username, query))
158-
})
159-
.map(|(username, id)| AutocompleteChoice::new(username.to_owned(), id.to_string()))
160-
.take(10)
161-
.collect()
172+
// fuzzy match on the username
173+
if a_score == 0 {
174+
a_score = fuzzy_match(query, a_name);
175+
}
176+
if b_score == 0 {
177+
b_score = fuzzy_match(query, b_name);
178+
}
179+
180+
if a_score != b_score {
181+
b_score.cmp(&a_score)
182+
} else {
183+
// score by id as tiebreaker
184+
a_id.cmp(b_id)
185+
}
186+
})
187+
.collect::<Vec<_>>();
188+
189+
choices.dedup();
190+
191+
choices
192+
.into_iter()
193+
.map(|(username, id)| AutocompleteChoice::new(username.to_owned(), id.to_string()))
194+
.take(10)
195+
.collect()
162196
}
163197

164198
fn get_online_users_matching(ctx: Context<'_>, partial: &str) -> Vec<ClientStateHandle> {
165199
let server = ctx.data().server().unwrap();
166-
let mut clients = server.handler().get_n_clients_matching(partial, 10);
200+
let mut clients = server.handler().get_n_clients_matching(partial, 25);
167201

168202
if let Ok(query_id) = partial.parse::<i32>() {
169203
if let Some(client) = server.handler().find_client(query_id) {

0 commit comments

Comments
 (0)