|
1 | | -use std::{cmp::Reverse, sync::Arc, time::Duration}; |
| 1 | +use std::{sync::Arc, time::Duration}; |
2 | 2 |
|
3 | 3 | use fuzzy_matcher::{FuzzyMatcher, skim::SkimMatcherV2}; |
4 | 4 | use itertools::Itertools; |
@@ -142,28 +142,62 @@ fn wrap_user_autocomplete<'a>( |
142 | 142 | query: &str, |
143 | 143 | iter: impl Iterator<Item = (&'a str, i32)>, |
144 | 144 | ) -> 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 | + } |
149 | 162 | } |
150 | | - } |
151 | 163 |
|
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 | + } |
155 | 171 |
|
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() |
162 | 196 | } |
163 | 197 |
|
164 | 198 | fn get_online_users_matching(ctx: Context<'_>, partial: &str) -> Vec<ClientStateHandle> { |
165 | 199 | 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); |
167 | 201 |
|
168 | 202 | if let Ok(query_id) = partial.parse::<i32>() { |
169 | 203 | if let Some(client) = server.handler().find_client(query_id) { |
|
0 commit comments