Skip to content

Commit

Permalink
LibGUI: Rank emoji search results based on query scores
Browse files Browse the repository at this point in the history
Now we only make calls to fuzzy_search() if the query is non-empty
because I assume calls to fuzzy_search() are expensive. Checking for if
the emoji belongs to the category is not done in
filter_and_rank_emojis() for this reason (in the case the query is empty
but a category is checked).
  • Loading branch information
ebanner committed Jul 6, 2024
1 parent f728053 commit db5782b
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 21 deletions.
58 changes: 37 additions & 21 deletions Userland/Libraries/LibGUI/EmojiInputDialog.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,32 @@ auto EmojiInputDialog::supported_emoji() -> Vector<Emoji>
return emojis;
}

Vector<EmojiInputDialog::Emoji> EmojiInputDialog::filter_and_rank_emojis(ByteString const& query)
{
Vector<EmojiScore> emoji_scores;

for (auto& emoji : m_emojis) {
if (emoji.emoji.name.is_empty()) {
continue;
}

auto result = fuzzy_match(query, emoji.emoji.name);
if (result.score > 0)
emoji_scores.append({ &emoji, result.score });
}

quick_sort(emoji_scores, [](auto const& lhs, auto const& rhs) {
return lhs.score > rhs.score;
});

Vector<Emoji> emojis;
for (auto& [emoji, _] : emoji_scores) {
emojis.append(*emoji);
}

return emojis;
}

void EmojiInputDialog::update_displayed_emoji()
{
ScopeGuard guard { [&] { m_emojis_widget->set_updates_enabled(true); } };
Expand All @@ -170,34 +196,24 @@ void EmojiInputDialog::update_displayed_emoji()

auto query = m_search_box->text();

for (size_t row = 0; row < rows && index < m_emojis.size(); ++row) {
Vector<Emoji> matching_emojis = query.is_empty() ? m_emojis : filter_and_rank_emojis(query);

for (size_t row = 0; row < rows && index < matching_emojis.size(); ++row) {
auto& horizontal_container = m_emojis_widget->add<Widget>();
horizontal_container.set_preferred_height(SpecialDimension::Fit);
horizontal_container.set_layout<HorizontalBoxLayout>(GUI::Margins {}, 0);

for (size_t column = 0; column < columns; ++column) {
bool found_match = false;

while (!found_match && (index < m_emojis.size())) {
auto& emoji = m_emojis[index++];

if (m_selected_category.has_value() && emoji.emoji.group != m_selected_category)
continue;
for (size_t column = 0; column < columns && index < matching_emojis.size(); ++index) {
auto& emoji = matching_emojis[index];

if (query.is_empty()) {
found_match = true;
} else if (!emoji.emoji.name.is_empty()) {
auto result = fuzzy_match(query, emoji.emoji.name);
found_match = result.score > 0;
}
if (m_selected_category.has_value() && emoji.emoji.group != m_selected_category)
continue;

if (found_match) {
horizontal_container.add_child(*emoji.button);
horizontal_container.add_child(*emoji.button);
if (m_first_displayed_emoji == nullptr)
m_first_displayed_emoji = &emoji;

if (m_first_displayed_emoji == nullptr)
m_first_displayed_emoji = &emoji;
}
}
column++;
}
}
}
Expand Down
6 changes: 6 additions & 0 deletions Userland/Libraries/LibGUI/EmojiInputDialog.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,15 @@ class EmojiInputDialog final : public Dialog {
private:
explicit EmojiInputDialog(Window* parent_window);

struct EmojiScore {
Emoji* emoji;
int score;
};

Vector<Emoji> supported_emoji();
void update_displayed_emoji();
void select_first_displayed_emoji();
Vector<Emoji> filter_and_rank_emojis(ByteString const& query);

OwnPtr<ActionGroup> m_category_action_group;
Optional<Unicode::EmojiGroup> m_selected_category;
Expand Down

0 comments on commit db5782b

Please sign in to comment.