diff options
| author | gwigz <gwigz@users.noreply.github.com> | 2026-06-18 22:04:45 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2026-06-19 00:04:45 +0300 |
| commit | 2c591b1429f44795aceebd5c6f5ea6907b2a08ea (patch) | |
| tree | 89f6416ea920acfc381a3f35f23de45ad3b4c98f /indra/newview/llfloaterimnearbychat.cpp | |
| parent | fc2e96135d0a55df5f3b668298fa72505d39413b (diff) | |
#5928 Gesture auto-complete, similar to emojis/mentions
Diffstat (limited to 'indra/newview/llfloaterimnearbychat.cpp')
| -rw-r--r-- | indra/newview/llfloaterimnearbychat.cpp | 100 |
1 files changed, 99 insertions, 1 deletions
diff --git a/indra/newview/llfloaterimnearbychat.cpp b/indra/newview/llfloaterimnearbychat.cpp index f0d696361a..8fa183b180 100644 --- a/indra/newview/llfloaterimnearbychat.cpp +++ b/indra/newview/llfloaterimnearbychat.cpp @@ -55,6 +55,7 @@ #include "llfloaterimnearbychatlistener.h" #include "llagent.h" // gAgent #include "llgesturemgr.h" +#include "llgestureautocompletehelper.h" #include "llmultigesture.h" #include "llkeyboard.h" #include "llanimationstates.h" @@ -70,6 +71,8 @@ #include "llautoreplace.h" #include "lluiusage.h" +#include <map> + S32 LLFloaterIMNearbyChat::sLastSpecialChatChannel = 0; static LLFloaterIMNearbyChatListener sChatListener; @@ -77,6 +80,72 @@ static LLFloaterIMNearbyChatListener sChatListener; constexpr S32 EXPANDED_HEIGHT = 266; constexpr S32 COLLAPSED_HEIGHT = 60; constexpr S32 EXPANDED_MIN_HEIGHT = 150; +constexpr size_t MAX_GESTURE_AUTOCOMPLETE_ROWS = 50; + +namespace +{ +bool buildGestureAutocompleteRows( + const std::string& prefix, + std::vector<LLGestureAutocompleteHelper::Row>& rows, + size_t& total, + std::string& empty_text) +{ + rows.clear(); + total = 0; + empty_text.clear(); + + // Wait for at least one character after the slash before offering matches. + if (prefix.size() < 2 || prefix[0] != '/' || prefix.find_first_of(" \t") != std::string::npos) + { + return false; + } + + std::string lower_prefix = prefix; + LLStringUtil::toLower(lower_prefix); + + std::map<std::string, std::string> unique; + const LLGestureMgr::item_map_t& active = LLGestureMgr::instance().getActiveGestures(); + + for (const auto& entry : active) + { + LLMultiGesture* gesture = entry.second; + + if (!gesture || gesture->getTrigger().empty() || gesture->getTrigger()[0] != '/') + { + continue; + } + + std::string lower_trigger = gesture->getTrigger(); + LLStringUtil::toLower(lower_trigger); + + if (lower_trigger.compare(0, lower_prefix.size(), lower_prefix) != 0) + { + continue; + } + + unique.emplace( + gesture->getTrigger(), + gesture->mName); + } + + for (const auto& gesture : unique) + { + ++total; + + if (rows.size() < MAX_GESTURE_AUTOCOMPLETE_ROWS) + { + rows.push_back({ gesture.first, gesture.first, gesture.second }); + } + } + + if (rows.empty()) + { + empty_text = "No matching gestures"; + } + + return total > 0; +} +} // legacy callback glue void send_chat_from_viewer(const std::string& utf8_out_text, EChatType type, S32 channel); @@ -501,8 +570,34 @@ void LLFloaterIMNearbyChat::onChatBoxKeystroke() KEY key = gKeyboard->currentKey(); + static LLCachedControl<bool> autocomplete_gestures(gSavedSettings, "ChatAutocompleteGestures", true); + + if (autocomplete_gestures) + { + std::vector<LLGestureAutocompleteHelper::Row> rows; + size_t total = 0; + std::string empty_text; + const std::string utf8_trigger = wstring_to_utf8str(raw_text); + + if (buildGestureAutocompleteRows(utf8_trigger, rows, total, empty_text)) + { + LLGestureAutocompleteHelper::instance().showHelper( + mInputEditor, + rows, + total, + empty_text, + [this](std::string trigger) + { + mInputEditor->setText(trigger + " "); + mInputEditor->endOfDoc(); + }); + return; + } + + LLGestureAutocompleteHelper::instance().hideHelper(mInputEditor); + } // Ignore "special" keys, like backspace, arrows, etc. - if (gSavedSettings.getBOOL("ChatAutocompleteGestures") + if (autocomplete_gestures && length > 1 && raw_text[0] == '/' && key < KEY_SPECIAL) @@ -589,6 +684,9 @@ void LLFloaterIMNearbyChat::sendChat( EChatType type ) LLWString text = mInputEditor->getConvertedText(); LLWStringUtil::trim(text); LLWStringUtil::replaceChar(text,182,'\n'); // Convert paragraph symbols back into newlines. + + LLGestureAutocompleteHelper::instance().hideHelper(); + if (!text.empty()) { // Check if this is destined for another channel |
