SL-20390 Emoji Completion floater - ignore symbols in shortcodes when searching by pattern

master
Alexander Gavriliuk 2023-10-05 11:28:54 +02:00 committed by Guru
parent 9f8763cae1
commit 98214577c3
4 changed files with 128 additions and 32 deletions

View File

@ -143,6 +143,70 @@ LLWString LLEmojiDictionary::findMatchingEmojis(const std::string& needle) const
return result;
}
void LLEmojiDictionary::findByShortCode(std::vector<LLEmojiSearchResult>& result, const std::string& needle) const
{
result.clear();
if (needle.empty() || needle.front() != ':')
return;
auto search = [needle](std::size_t& begin, std::size_t& end, const std::string& shortCode) -> bool
{
begin = 0;
end = 1;
std::size_t index = 1;
// Search for begin
char d = tolower(needle[index++]);
while (end < shortCode.size())
{
char s = tolower(shortCode[end++]);
if (s == d)
{
begin = end - 1;
break;
}
}
if (!begin)
return false;
// Search for end
d = tolower(needle[index++]);
while (end < shortCode.size() && index <= needle.size())
{
char s = tolower(shortCode[end++]);
if (s == d)
{
if (index == needle.size())
return true;
d = tolower(needle[index++]);
continue;
}
switch (s)
{
case L'-':
case L'_':
case L'+':
continue;
}
break;
}
return false;
};
for (const LLEmojiDescriptor& d : mEmojis)
{
if (d.ShortCodes.empty())
continue;
const std::string& shortCode = d.ShortCodes.front();
if (shortCode.size() < needle.size() || shortCode.front() != needle.front())
continue;
std::size_t begin, end;
if (search(begin, end, shortCode))
{
result.emplace_back(d.Character, shortCode, begin, end);
}
}
}
const LLEmojiDescriptor* LLEmojiDictionary::getDescriptorFromEmoji(llwchar emoji) const
{
const auto it = mEmoji2Descr.find(emoji);

View File

@ -52,6 +52,25 @@ struct LLEmojiGroup
std::list<std::string> Categories;
};
// ============================================================================
// LLEmojiSearchResult class
//
struct LLEmojiSearchResult
{
llwchar Character;
std::string String;
std::size_t Begin, End;
LLEmojiSearchResult(llwchar character, const std::string& string, std::size_t begin, std::size_t end)
: Character(character)
, String(string)
, Begin(begin)
, End(end)
{
}
};
// ============================================================================
// LLEmojiDictionary class
//
@ -70,6 +89,7 @@ public:
static void initClass();
LLWString findMatchingEmojis(const std::string& needle) const;
void findByShortCode(std::vector<LLEmojiSearchResult>& result, const std::string& needle) const;
const LLEmojiDescriptor* getDescriptorFromEmoji(llwchar emoji) const;
const LLEmojiDescriptor* getDescriptorFromShortCode(const std::string& short_code) const;
std::string getNameFromEmoji(llwchar ch) const;

View File

@ -82,7 +82,7 @@ void LLPanelEmojiComplete::draw()
{
LLUICtrl::draw();
if (mEmojis.empty())
if (!mTotalEmojis)
return;
const size_t firstVisibleIdx = mScrollPos;
@ -115,21 +115,16 @@ void LLPanelEmojiComplete::draw()
for (U32 curIdx = firstVisibleIdx; curIdx < lastVisibleIdx; curIdx++)
{
mIconFont->render(mEmojis, curIdx, iconCenterX, iconCenterY,
LLWString text(1, mEmojis[curIdx].Character);
mIconFont->render(text, 0, iconCenterX, iconCenterY,
LLColor4::white, LLFontGL::HCENTER, LLFontGL::VCENTER, LLFontGL::NORMAL,
LLFontGL::DROP_SHADOW_SOFT, 1, S32_MAX, nullptr, false, true);
if (mVertical)
{
llwchar emoji = mEmojis[curIdx];
auto& emoji2descr = LLEmojiDictionary::instance().getEmoji2Descr();
auto it = emoji2descr.find(emoji);
if (it != emoji2descr.end())
{
const std::string& shortCode = it->second->ShortCodes.front();
mTextFont->renderUTF8(shortCode, 0, textLeft, iconCenterY, LLColor4::white,
LLFontGL::LEFT, LLFontGL::VCENTER, LLFontGL::NORMAL, LLFontGL::NO_SHADOW,
shortCode.size(), textWidth, NULL, FALSE, FALSE);
}
const std::string& shortCode = mEmojis[curIdx].String;
mTextFont->renderUTF8(shortCode, 0, textLeft, iconCenterY, LLColor4::white,
LLFontGL::LEFT, LLFontGL::VCENTER, LLFontGL::NORMAL, LLFontGL::NO_SHADOW,
shortCode.size(), textWidth, NULL, FALSE, FALSE);
iconCenterY -= mEmojiHeight;
}
else
@ -257,9 +252,8 @@ void LLPanelEmojiComplete::onCommit()
{
if (mCurSelected < mTotalEmojis)
{
LLWString wstr;
wstr.push_back(mEmojis.at(mCurSelected));
setValue(wstring_to_utf8str(wstr));
LLSD value(wstring_to_utf8str(LLWString(1, mEmojis[mCurSelected].Character)));
setValue(value);
LLUICtrl::onCommit();
}
}
@ -272,7 +266,23 @@ void LLPanelEmojiComplete::reshape(S32 width, S32 height, BOOL called_from_paren
void LLPanelEmojiComplete::setEmojis(const LLWString& emojis)
{
mEmojis = emojis;
mEmojis.clear();
auto& emoji2descr = LLEmojiDictionary::instance().getEmoji2Descr();
for (const llwchar& emoji : emojis)
{
std::string shortCode;
if (mVertical)
{
auto it = emoji2descr.find(emoji);
if (it != emoji2descr.end() && !it->second->ShortCodes.empty())
{
shortCode = it->second->ShortCodes.front();
}
}
mEmojis.emplace_back(emoji, shortCode, 0, 0);
}
mTotalEmojis = mEmojis.size();
mCurSelected = 0;
@ -281,12 +291,20 @@ void LLPanelEmojiComplete::setEmojis(const LLWString& emojis)
void LLPanelEmojiComplete::setEmojiHint(const std::string& hint)
{
llwchar curEmoji = mCurSelected < mTotalEmojis ? mEmojis.at(mCurSelected) : 0;
llwchar curEmoji = mCurSelected < mTotalEmojis ? mEmojis[mCurSelected].Character : 0;
mEmojis = LLEmojiDictionary::instance().findMatchingEmojis(hint);
LLEmojiDictionary::instance().findByShortCode(mEmojis, hint);
mTotalEmojis = mEmojis.size();
size_t curEmojiIdx = curEmoji ? mEmojis.find(curEmoji) : std::string::npos;
mCurSelected = std::string::npos != curEmojiIdx ? curEmojiIdx : 0;
mCurSelected = 0;
for (size_t i = 1; i < mTotalEmojis; ++i)
{
if (mEmojis[i].Character == curEmoji)
{
mCurSelected = i;
break;
}
}
onEmojisChanged();
}
@ -294,18 +312,12 @@ void LLPanelEmojiComplete::setEmojiHint(const std::string& hint)
U32 LLPanelEmojiComplete::getMaxShortCodeWidth() const
{
U32 max_width = 0;
auto& emoji2descr = LLEmojiDictionary::instance().getEmoji2Descr();
for (llwchar emoji : mEmojis)
for (const LLEmojiSearchResult& result : mEmojis)
{
auto it = emoji2descr.find(emoji);
if (it != emoji2descr.end())
S32 width = mTextFont->getWidth(result.String);
if (width > max_width)
{
const std::string& shortCode = it->second->ShortCodes.front();
S32 width = mTextFont->getWidth(shortCode);
if (width > max_width)
{
max_width = width;
}
max_width = width;
}
}
return max_width;

View File

@ -26,6 +26,7 @@
#pragma once
#include "llemojidictionary.h"
#include "llfloater.h"
#include "lluictrl.h"
@ -68,7 +69,6 @@ public:
void reshape(S32 width, S32 height, BOOL called_from_parent) override;
public:
const LLWString& getEmojis() const { return mEmojis; }
size_t getEmojiCount() const { return mEmojis.size(); }
void setEmojis(const LLWString& emojis);
void setEmojiHint(const std::string& hint);
@ -95,7 +95,7 @@ protected:
const LLFontGL* mIconFont;
const LLFontGL* mTextFont;
LLWString mEmojis;
std::vector<LLEmojiSearchResult> mEmojis;
LLScrollbar* mScrollbar;
LLRect mRenderRect;
U16 mEmojiWidth = 0;