From 0cc9a2d8fd54ea5ed906597f2f922a85265bdd03 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Fri, 25 Aug 2023 19:18:52 +0300 Subject: [PATCH 1/7] MacOS gmock build fix Updated gmock complains about missing regex_t. This is likely a macos configuration issue and needs to be fixed, but fot now just forcing the declaration --- indra/test/test.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/indra/test/test.cpp b/indra/test/test.cpp index bb48216b2b..cae9d4f5fd 100644 --- a/indra/test/test.cpp +++ b/indra/test/test.cpp @@ -54,6 +54,12 @@ #endif #ifndef LL_WINDOWS + +typedef struct { + void *re_pcre; + size_t re_nsub; + size_t re_erroffset; +} regex_t; #include #include #endif From 031032fb892560a0f5fa1a996aea77f593f54704 Mon Sep 17 00:00:00 2001 From: Alexander Gavriliuk Date: Tue, 29 Aug 2023 13:12:09 +0200 Subject: [PATCH 2/7] SL-20211 EmojiPicker - The search field should be the same as other floaters --- indra/llui/llsearcheditor.cpp | 4 ++++ indra/newview/llfloateremojipicker.cpp | 10 +++++----- indra/newview/llfloateremojipicker.h | 4 ++-- .../skins/default/xui/en/floater_emoji_picker.xml | 9 ++------- 4 files changed, 13 insertions(+), 14 deletions(-) diff --git a/indra/llui/llsearcheditor.cpp b/indra/llui/llsearcheditor.cpp index bafeef41fb..cfaf08ec0a 100644 --- a/indra/llui/llsearcheditor.cpp +++ b/indra/llui/llsearcheditor.cpp @@ -178,6 +178,10 @@ void LLSearchEditor::setFocus( BOOL b ) void LLSearchEditor::onClearButtonClick(const LLSD& data) { setText(LLStringUtil::null); + if (mTextChangedCallback) + { + mTextChangedCallback(this, getValue()); + } mSearchEditor->onCommit(); // force keystroke callback } diff --git a/indra/newview/llfloateremojipicker.cpp b/indra/newview/llfloateremojipicker.cpp index c3344fc18a..af807ba7cf 100644 --- a/indra/newview/llfloateremojipicker.cpp +++ b/indra/newview/llfloateremojipicker.cpp @@ -31,9 +31,9 @@ #include "llbutton.h" #include "llcombobox.h" #include "llemojidictionary.h" +#include "llfiltereditor.h" #include "llfloaterreg.h" #include "llkeyboard.h" -#include "lllineeditor.h" #include "llscrollcontainer.h" #include "llscrollingpanellist.h" #include "llscrolllistctrl.h" @@ -294,9 +294,9 @@ BOOL LLFloaterEmojiPicker::postBuild() mGroups = getChild("Groups"); mBadge = getChild("Badge"); - mFilter = getChild("Filter"); - mFilter->setKeystrokeCallback([this](LLLineEditor*, void*) { onSearchKeystroke(); }, NULL); - mFilter->setFont(LLViewerChat::getChatFont()); + mFilter = getChild("Filter"); + mFilter->setKeystrokeCallback([this](LLUICtrl*, const LLSD&) { onFilterChanged(); }); + mFilter->setTextChangedCallback([this](LLUICtrl*, const LLSD&) { onFilterChanged(); }); mFilter->setText(sFilterPattern); mEmojiScroll = getChild("EmojiGridContainer"); @@ -588,7 +588,7 @@ void LLFloaterEmojiPicker::onGroupButtonClick(LLUICtrl* ctrl) } } -void LLFloaterEmojiPicker::onSearchKeystroke() +void LLFloaterEmojiPicker::onFilterChanged() { sFilterPattern = mFilter->getText(); fillEmojis(); diff --git a/indra/newview/llfloateremojipicker.h b/indra/newview/llfloateremojipicker.h index e4b1216ce6..3cae818e15 100644 --- a/indra/newview/llfloateremojipicker.h +++ b/indra/newview/llfloateremojipicker.h @@ -60,7 +60,7 @@ private: void fillEmojis(bool fromResize = false); void onGroupButtonClick(LLUICtrl* ctrl); - void onSearchKeystroke(); + void onFilterChanged(); void onGridMouseEnter(); void onGridMouseLeave(); void onGroupButtonMouseEnter(LLUICtrl* ctrl); @@ -81,7 +81,7 @@ private: class LLPanel* mGroups { nullptr }; class LLPanel* mBadge { nullptr }; - class LLLineEditor* mFilter { nullptr }; + class LLFilterEditor* mFilter { nullptr }; class LLScrollContainer* mEmojiScroll { nullptr }; class LLScrollingPanelList* mEmojiGrid { nullptr }; class LLEmojiPreviewPanel* mPreview { nullptr }; diff --git a/indra/newview/skins/default/xui/en/floater_emoji_picker.xml b/indra/newview/skins/default/xui/en/floater_emoji_picker.xml index a2a290c306..6c440de573 100644 --- a/indra/newview/skins/default/xui/en/floater_emoji_picker.xml +++ b/indra/newview/skins/default/xui/en/floater_emoji_picker.xml @@ -12,19 +12,14 @@ width="250"> - Date: Tue, 29 Aug 2023 14:23:48 +0200 Subject: [PATCH 3/7] SL-20209 Open read access to the recently used emojis --- indra/newview/llfloateremojipicker.cpp | 10 ++++++++++ indra/newview/llfloateremojipicker.h | 9 +++++---- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/indra/newview/llfloateremojipicker.cpp b/indra/newview/llfloateremojipicker.cpp index af807ba7cf..95ea9fc478 100644 --- a/indra/newview/llfloateremojipicker.cpp +++ b/indra/newview/llfloateremojipicker.cpp @@ -723,6 +723,14 @@ void LLFloaterEmojiPicker::closeFloater(bool app_quitting) } } +// static +std::list& LLFloaterEmojiPicker::getRecentlyUsed() +{ + loadState(); + return sRecentlyUsed; +} + +// static void LLFloaterEmojiPicker::onEmojiUsed(llwchar emoji) { // Update sRecentlyUsed @@ -762,6 +770,7 @@ void LLFloaterEmojiPicker::onEmojiUsed(llwchar emoji) sFrequentlyUsed.push_back(std::make_pair(emoji, 1)); } +// static void LLFloaterEmojiPicker::loadState() { if (!sStateFileName.empty()) @@ -844,6 +853,7 @@ void LLFloaterEmojiPicker::loadState() } } +// static void LLFloaterEmojiPicker::saveState() { if (sStateFileName.empty()) diff --git a/indra/newview/llfloateremojipicker.h b/indra/newview/llfloateremojipicker.h index 3cae818e15..decee41721 100644 --- a/indra/newview/llfloateremojipicker.h +++ b/indra/newview/llfloateremojipicker.h @@ -54,6 +54,11 @@ public: virtual void closeFloater(bool app_quitting = false) override; + static std::list& getRecentlyUsed(); + static void onEmojiUsed(llwchar emoji); + static void loadState(); + static void saveState(); + private: void fillGroups(); void moveGroups(); @@ -75,10 +80,6 @@ private: virtual BOOL handleKeyHere(KEY key, MASK mask) override; - void onEmojiUsed(llwchar emoji); - void loadState(); - void saveState(); - class LLPanel* mGroups { nullptr }; class LLPanel* mBadge { nullptr }; class LLFilterEditor* mFilter { nullptr }; From b9de65d2750c0f5632116864af792c40078830ab Mon Sep 17 00:00:00 2001 From: Alexander Gavriliuk Date: Tue, 29 Aug 2023 15:07:41 +0200 Subject: [PATCH 4/7] SL-20209 Add 'noscroll' parameter to LLPanelEmojiComplete::Params --- indra/newview/llpanelemojicomplete.cpp | 25 ++++++++++++++++++++++--- indra/newview/llpanelemojicomplete.h | 17 ++++++++++++----- 2 files changed, 34 insertions(+), 8 deletions(-) diff --git a/indra/newview/llpanelemojicomplete.cpp b/indra/newview/llpanelemojicomplete.cpp index 8b89e3aa14..8fc84c0387 100644 --- a/indra/newview/llpanelemojicomplete.cpp +++ b/indra/newview/llpanelemojicomplete.cpp @@ -41,6 +41,7 @@ static LLDefaultChildRegistry::Register r("emoji_complete" LLPanelEmojiComplete::Params::Params() : autosize("autosize") + , noscroll("noscroll") , max_emoji("max_emoji") , padding("padding") , selected_image("selected_image") @@ -50,6 +51,7 @@ LLPanelEmojiComplete::Params::Params() LLPanelEmojiComplete::LLPanelEmojiComplete(const LLPanelEmojiComplete::Params& p) : LLUICtrl(p) , mAutoSize(p.autosize) + , mNoScroll(p.noscroll) , mMaxVisible(p.max_emoji) , mPadding(p.padding) , mSelectedImage(p.selected_image) @@ -152,7 +154,7 @@ BOOL LLPanelEmojiComplete::handleMouseUp(S32 x, S32 y, MASK mask) void LLPanelEmojiComplete::onCommit() { - if (npos != mCurSelected) + if (mCurSelected < mEmojis.size()) { LLWString wstr; wstr.push_back(mEmojis.at(mCurSelected)); @@ -167,6 +169,14 @@ void LLPanelEmojiComplete::reshape(S32 width, S32 height, BOOL called_from_paren updateConstraints(); } +void LLPanelEmojiComplete::setEmojis(const LLWString& emojis) +{ + mEmojis = emojis; + mCurSelected = 0; + + onEmojisChanged(); +} + void LLPanelEmojiComplete::setEmojiHint(const std::string& hint) { llwchar curEmoji = (mCurSelected < mEmojis.size()) ? mEmojis.at(mCurSelected) : 0; @@ -175,6 +185,11 @@ void LLPanelEmojiComplete::setEmojiHint(const std::string& hint) size_t curEmojiIdx = (curEmoji) ? mEmojis.find(curEmoji) : std::string::npos; mCurSelected = (std::string::npos != curEmojiIdx) ? curEmojiIdx : 0; + onEmojisChanged(); +} + +void LLPanelEmojiComplete::onEmojisChanged() +{ if (mAutoSize) { mVisibleEmojis = std::min(mEmojis.size(), mMaxVisible); @@ -233,9 +248,13 @@ void LLPanelEmojiComplete::updateConstraints() void LLPanelEmojiComplete::updateScrollPos() { const size_t cntEmoji = mEmojis.size(); - if (0 == cntEmoji || cntEmoji < mVisibleEmojis || 0 == mCurSelected) + if (mNoScroll || 0 == cntEmoji || cntEmoji < mVisibleEmojis || 0 == mCurSelected) { mScrollPos = 0; + if (mCurSelected >= mVisibleEmojis) + { + mCurSelected = mVisibleEmojis ? mVisibleEmojis - 1 : 0; + } } else if (cntEmoji - 1 == mCurSelected) { @@ -273,11 +292,11 @@ BOOL LLFloaterEmojiComplete::handleKey(KEY key, MASK mask, BOOL called_from_pare handled = true; break; } - } if (handled) return TRUE; + return LLFloater::handleKey(key, mask, called_from_parent); } diff --git a/indra/newview/llpanelemojicomplete.h b/indra/newview/llpanelemojicomplete.h index aa0f806525..3456de4044 100644 --- a/indra/newview/llpanelemojicomplete.h +++ b/indra/newview/llpanelemojicomplete.h @@ -40,6 +40,7 @@ public: struct Params : public LLInitParam::Block { Optional autosize; + Optional noscroll; Optional max_emoji, padding; @@ -50,6 +51,7 @@ public: protected: LLPanelEmojiComplete(const LLPanelEmojiComplete::Params&); + public: virtual ~LLPanelEmojiComplete(); @@ -62,9 +64,13 @@ 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 setEmojiHint(const std::string& hint); + void setEmojis(const LLWString& emojis); + void setEmojiHint(const std::string& hint); + protected: + void LLPanelEmojiComplete::onEmojisChanged(); size_t posToIndex(S32 x, S32 y) const; void select(size_t emoji_idx); void selectNext(); @@ -76,13 +82,14 @@ protected: protected: static constexpr auto npos = std::numeric_limits::max(); - bool mAutoSize = false; + const bool mAutoSize = false; + const bool mNoScroll = false; const LLFontGL* mFont; U16 mEmojiWidth = 0; - size_t mMaxVisible = 0; - S32 mPadding = 8; + const size_t mMaxVisible = 0; + const S32 mPadding = 8; LLRect mRenderRect; - LLUIImagePtr mSelectedImage; + const LLUIImagePtr mSelectedImage; LLWString mEmojis; size_t mVisibleEmojis = 0; From f18746a1753fc8d5338fcaeb839540a071c68b13 Mon Sep 17 00:00:00 2001 From: Alexander Gavriliuk Date: Tue, 29 Aug 2023 15:31:03 +0200 Subject: [PATCH 5/7] SL-20209 EmojiPicker - Show 'Recent' panel instead of the floater on click the button --- indra/newview/llfloaterimsessiontab.cpp | 301 +++++++++++------- indra/newview/llfloaterimsessiontab.h | 44 +-- .../default/xui/en/floater_im_session.xml | 41 ++- 3 files changed, 252 insertions(+), 134 deletions(-) diff --git a/indra/newview/llfloaterimsessiontab.cpp b/indra/newview/llfloaterimsessiontab.cpp index bacfd8ca33..61722a823f 100644 --- a/indra/newview/llfloaterimsessiontab.cpp +++ b/indra/newview/llfloaterimsessiontab.cpp @@ -33,7 +33,6 @@ #include "llagentcamera.h" #include "llavataractions.h" #include "llavatariconctrl.h" -#include "llgroupiconctrl.h" #include "llchatentry.h" #include "llchathistory.h" #include "llchiclet.h" @@ -43,9 +42,11 @@ #include "llfloateremojipicker.h" #include "llfloaterimsession.h" #include "llfloaterimcontainer.h" // to replace separate IM Floaters with multifloater container -#include "lllayoutstack.h" -#include "lltoolbarview.h" #include "llfloaterimnearbychat.h" +#include "llgroupiconctrl.h" +#include "lllayoutstack.h" +#include "llpanelemojicomplete.h" +#include "lltoolbarview.h" const F32 REFRESH_INTERVAL = 1.0f; const std::string ICN_GROUP("group_chat_icon"); @@ -57,7 +58,7 @@ void cb_group_do_nothing() } LLFloaterIMSessionTab::LLFloaterIMSessionTab(const LLSD& session_id) -: LLTransientDockableFloater(NULL, false, session_id), +: super(NULL, false, session_id), mIsP2PChat(false), mExpandCollapseBtn(NULL), mTearOffBtn(NULL), @@ -76,7 +77,7 @@ LLFloaterIMSessionTab::LLFloaterIMSessionTab(const LLSD& session_id) mInputPanels(NULL), mChatLayoutPanelHeight(0) { - setAutoFocus(FALSE); + setAutoFocus(FALSE); mSession = LLIMModel::getInstance()->findIMSession(mSessionID); mCommitCallbackRegistrar.add("IMSession.Menu.Action", @@ -89,12 +90,12 @@ LLFloaterIMSessionTab::LLFloaterIMSessionTab(const LLSD& session_id) boost::bind(&LLFloaterIMSessionTab::onIMShowModesMenuItemEnable, this, _2)); // Right click menu handling - mEnableCallbackRegistrar.add("Avatar.CheckItem", boost::bind(&LLFloaterIMSessionTab::checkContextMenuItem, this, _2)); - mEnableCallbackRegistrar.add("Avatar.EnableItem", boost::bind(&LLFloaterIMSessionTab::enableContextMenuItem, this, _2)); - mCommitCallbackRegistrar.add("Avatar.DoToSelected", boost::bind(&LLFloaterIMSessionTab::doToSelected, this, _2)); - mCommitCallbackRegistrar.add("Group.DoToSelected", boost::bind(&cb_group_do_nothing)); + mEnableCallbackRegistrar.add("Avatar.CheckItem", boost::bind(&LLFloaterIMSessionTab::checkContextMenuItem, this, _2)); + mEnableCallbackRegistrar.add("Avatar.EnableItem", boost::bind(&LLFloaterIMSessionTab::enableContextMenuItem, this, _2)); + mCommitCallbackRegistrar.add("Avatar.DoToSelected", boost::bind(&LLFloaterIMSessionTab::doToSelected, this, _2)); + mCommitCallbackRegistrar.add("Group.DoToSelected", boost::bind(&cb_group_do_nothing)); - mMinFloaterHeight = getMinHeight(); + mMinFloaterHeight = getMinHeight(); } LLFloaterIMSessionTab::~LLFloaterIMSessionTab() @@ -102,7 +103,7 @@ LLFloaterIMSessionTab::~LLFloaterIMSessionTab() delete mRefreshTimer; } -//static +// static LLFloaterIMSessionTab* LLFloaterIMSessionTab::findConversation(const LLUUID& uuid) { LLFloaterIMSessionTab* conv; @@ -119,7 +120,7 @@ LLFloaterIMSessionTab* LLFloaterIMSessionTab::findConversation(const LLUUID& uui return conv; }; -//static +// static LLFloaterIMSessionTab* LLFloaterIMSessionTab::getConversation(const LLUUID& uuid) { LLFloaterIMSessionTab* conv; @@ -135,14 +136,16 @@ LLFloaterIMSessionTab* LLFloaterIMSessionTab::getConversation(const LLUUID& uuid } return conv; + }; +// virtual void LLFloaterIMSessionTab::setVisible(BOOL visible) { - if(visible && !mHasVisibleBeenInitialized) + if (visible && !mHasVisibleBeenInitialized) { mHasVisibleBeenInitialized = true; - if(!gAgentCamera.cameraMouselook()) + if (!gAgentCamera.cameraMouselook()) { LLFloaterReg::getTypedInstance("im_container")->setVisible(true); } @@ -156,27 +159,26 @@ void LLFloaterIMSessionTab::setVisible(BOOL visible) mInputButtonPanel->setVisible(isTornOff()); } - LLTransientDockableFloater::setVisible(visible); + super::setVisible(visible); } -/*virtual*/ +// virtual void LLFloaterIMSessionTab::setFocus(BOOL focus) { - LLTransientDockableFloater::setFocus(focus); + super::setFocus(focus); - //Redirect focus to input editor - if (focus) + // Redirect focus to input editor + if (focus) { - updateMessages(); + updateMessages(); - if (mInputEditor) - { - mInputEditor->setFocus(TRUE); - } + if (mInputEditor) + { + mInputEditor->setFocus(TRUE); + } } } - void LLFloaterIMSessionTab::addToHost(const LLUUID& session_id) { if ((session_id.notNull() && !gIMMgr->hasSession(session_id)) @@ -221,44 +223,58 @@ void LLFloaterIMSessionTab::assignResizeLimits() { bool is_participants_pane_collapsed = mParticipantListPanel->isCollapsed(); - // disable a layoutstack's functionality when participant list panel is collapsed + // disable a layoutstack's functionality when participant list panel is collapsed mRightPartPanel->setIgnoreReshape(is_participants_pane_collapsed); - S32 participants_pane_target_width = is_participants_pane_collapsed? - 0 : (mParticipantListPanel->getRect().getWidth() + mParticipantListAndHistoryStack->getPanelSpacing()); + S32 participants_pane_target_width = is_participants_pane_collapsed? + 0 : (mParticipantListPanel->getRect().getWidth() + mParticipantListAndHistoryStack->getPanelSpacing()); - S32 new_min_width = participants_pane_target_width + mRightPartPanel->getExpandedMinDim() + mFloaterExtraWidth; + S32 new_min_width = participants_pane_target_width + mRightPartPanel->getExpandedMinDim() + mFloaterExtraWidth; setResizeLimits(new_min_width, getMinHeight()); this->mParticipantListAndHistoryStack->updateLayout(); } +// virtual BOOL LLFloaterIMSessionTab::postBuild() { BOOL result; mBodyStack = getChild("main_stack"); - mParticipantListAndHistoryStack = getChild("im_panels"); + mParticipantListAndHistoryStack = getChild("im_panels"); mCloseBtn = getChild("close_btn"); - mCloseBtn->setCommitCallback(boost::bind(&LLFloater::onClickClose, this)); + mCloseBtn->setCommitCallback([this](LLUICtrl*, const LLSD&) { onClickClose(this); }); mExpandCollapseBtn = getChild("expand_collapse_btn"); - mExpandCollapseBtn->setClickedCallback(boost::bind(&LLFloaterIMSessionTab::onSlide, this)); + mExpandCollapseBtn->setClickedCallback([this](LLUICtrl*, const LLSD&) { onSlide(this); }); mExpandCollapseLineBtn = getChild("minz_btn"); - mExpandCollapseLineBtn->setClickedCallback(boost::bind(&LLFloaterIMSessionTab::onCollapseToLine, this)); + mExpandCollapseLineBtn->setClickedCallback([this](LLUICtrl*, const LLSD&) { onCollapseToLine(this); }); mTearOffBtn = getChild("tear_off_btn"); mTearOffBtn->setCommitCallback(boost::bind(&LLFloaterIMSessionTab::onTearOffClicked, this)); - mEmojiBtn = getChild("emoji_panel_btn"); - mEmojiBtn->setLabel(LLUIString(LLWString(1, 128512))); - mEmojiBtn->setClickedCallback(boost::bind(&LLFloaterIMSessionTab::onEmojiPanelBtnClicked, this)); + mEmojiRecentPanelToggleBtn = getChild("emoji_recent_panel_toggle_btn"); + mEmojiRecentPanelToggleBtn->setLabel(LLUIString(LLWString(1, 128512))); + mEmojiRecentPanelToggleBtn->setClickedCallback([this](LLUICtrl*, const LLSD&) { onEmojiRecentPanelToggleBtnClicked(this); }); + + mEmojiRecentPanel = getChild("emoji_recent_layout_panel"); + mEmojiRecentPanel->setVisible(false); + + mEmojiRecentEmptyText = getChildView("emoji_recent_empty_text"); + mEmojiRecentEmptyText->setVisible(false); + + mEmojiRecentIconsCtrl = getChild("emoji_recent_icons_ctrl"); + mEmojiRecentIconsCtrl->setCommitCallback([this](LLUICtrl*, const LLSD& value) { onRecentEmojiPicked(value); }); + mEmojiRecentIconsCtrl->setVisible(false); + + mEmojiPickerToggleBtn = getChild("emoji_picker_toggle_btn"); + mEmojiPickerToggleBtn->setClickedCallback([this](LLUICtrl*, const LLSD&) { onEmojiPickerToggleBtnClicked(this); }); mGearBtn = getChild("gear_btn"); - mAddBtn = getChild("add_btn"); + mAddBtn = getChild("add_btn"); mVoiceButton = getChild("voice_call_btn"); mParticipantListPanel = getChild("speakers_list_panel"); @@ -312,17 +328,17 @@ BOOL LLFloaterIMSessionTab::postBuild() // Create the root using an ad-hoc base item LLConversationItem* base_item = new LLConversationItem(mSessionID, mConversationViewModel); - LLFolderView::Params p(LLUICtrlFactory::getDefaultParams()); - p.rect = LLRect(0, 0, getRect().getWidth(), 0); - p.parent_panel = mParticipantListPanel; - p.listener = base_item; - p.view_model = &mConversationViewModel; - p.root = NULL; - p.use_ellipses = true; - p.options_menu = "menu_conversation.xml"; - p.name = "root"; + LLFolderView::Params p(LLUICtrlFactory::getDefaultParams()); + p.rect = LLRect(0, 0, getRect().getWidth(), 0); + p.parent_panel = mParticipantListPanel; + p.listener = base_item; + p.view_model = &mConversationViewModel; + p.root = NULL; + p.use_ellipses = true; + p.options_menu = "menu_conversation.xml"; + p.name = "root"; mConversationsRoot = LLUICtrlFactory::create(p); - mConversationsRoot->setCallbackRegistrar(&mCommitCallbackRegistrar); + mConversationsRoot->setCallbackRegistrar(&mCommitCallbackRegistrar); mConversationsRoot->setEnableRegistrar(&mEnableCallbackRegistrar); // Attach that root to the scroller mScroller->addChild(mConversationsRoot); @@ -362,6 +378,7 @@ LLParticipantList* LLFloaterIMSessionTab::getParticipantList() return dynamic_cast(LLFloaterIMContainer::getInstance()->getSessionModel(mSessionID)); } +// virtual void LLFloaterIMSessionTab::draw() { if (mRefreshTimer->hasExpired()) @@ -386,23 +403,24 @@ void LLFloaterIMSessionTab::draw() mRefreshTimer->setTimerExpirySec(REFRESH_INTERVAL); } - LLTransientDockableFloater::draw(); + super::draw(); } void LLFloaterIMSessionTab::enableDisableCallBtn() { - if (LLVoiceClient::instanceExists() && mVoiceButton) - { - mVoiceButton->setEnabled( - mSessionID.notNull() - && mSession - && mSession->mSessionInitialized - && LLVoiceClient::getInstance()->voiceEnabled() - && LLVoiceClient::getInstance()->isVoiceWorking() - && mSession->mCallBackEnabled); - } + if (LLVoiceClient::instanceExists() && mVoiceButton) + { + mVoiceButton->setEnabled( + mSessionID.notNull() + && mSession + && mSession->mSessionInitialized + && LLVoiceClient::getInstance()->voiceEnabled() + && LLVoiceClient::getInstance()->isVoiceWorking() + && mSession->mCallBackEnabled); + } } +// virtual void LLFloaterIMSessionTab::onFocusReceived() { setBackgroundOpaque(true); @@ -412,13 +430,14 @@ void LLFloaterIMSessionTab::onFocusReceived() LLIMModel::instance().sendNoUnreadMessages(mSessionID); } - LLTransientDockableFloater::onFocusReceived(); + super::onFocusReceived(); } +// virtual void LLFloaterIMSessionTab::onFocusLost() { setBackgroundOpaque(false); - LLTransientDockableFloater::onFocusLost(); + super::onFocusLost(); } void LLFloaterIMSessionTab::onInputEditorClicked() @@ -431,7 +450,17 @@ void LLFloaterIMSessionTab::onInputEditorClicked() gToolBarView->flashCommand(LLCommandId("chat"), false); } -void LLFloaterIMSessionTab::onEmojiPanelBtnClicked(LLFloaterIMSessionTab* self) +void LLFloaterIMSessionTab::onEmojiRecentPanelToggleBtnClicked(LLFloaterIMSessionTab* self) +{ + BOOL show = !self->mEmojiRecentPanel->getVisible(); + if (show) + { + self->onEmojiRecentPanelOpening(); + } + self->mEmojiRecentPanel->setVisible(show); +} + +void LLFloaterIMSessionTab::onEmojiPickerToggleBtnClicked(LLFloaterIMSessionTab* self) { if (LLFloaterEmojiPicker* picker = LLFloaterEmojiPicker::getInstance()) { @@ -452,6 +481,44 @@ void LLFloaterIMSessionTab::onEmojiPanelBtnClicked(LLFloaterIMSessionTab* self) } } +void LLFloaterIMSessionTab::onEmojiRecentPanelOpening() +{ + std::list& recentlyUsed = LLFloaterEmojiPicker::getRecentlyUsed(); + if (recentlyUsed.empty()) + { + mEmojiRecentEmptyText->setVisible(true); + mEmojiRecentIconsCtrl->setVisible(false); + mEmojiPickerToggleBtn->setFocus(true); + } + else + { + LLWString emojis; + for (llwchar emoji : recentlyUsed) + { + emojis += emoji; + } + mEmojiRecentIconsCtrl->setEmojis(emojis); + mEmojiRecentEmptyText->setVisible(false); + mEmojiRecentIconsCtrl->setVisible(true); + mEmojiRecentIconsCtrl->setFocus(true); + } +} + +void LLFloaterIMSessionTab::onRecentEmojiPicked(const LLSD& value) +{ + LLSD::String str = value.asString(); + if (str.size()) + { + LLWString wstr = utf8string_to_wstring(str); + if (wstr.size()) + { + llwchar emoji = wstr[0]; + LLFloaterEmojiPicker::onEmojiUsed(emoji); + onEmojiPicked(emoji); + } + } +} + void LLFloaterIMSessionTab::onEmojiPicked(llwchar emoji) { mInputEditor->insertEmoji(emoji); @@ -462,6 +529,12 @@ void LLFloaterIMSessionTab::onEmojiPickerClosed() mInputEditor->setFocus(TRUE); } +void LLFloaterIMSessionTab::closeFloater(bool app_quitting) +{ + LLFloaterEmojiPicker::saveState(); + super::closeFloater(app_quitting); +} + std::string LLFloaterIMSessionTab::appendTime() { std::string timeStr = "[" + LLTrans::getString("TimeHour") + "]:" @@ -530,10 +603,10 @@ void LLFloaterIMSessionTab::buildConversationViewParticipant() while (current_participant_model != end_participant_model) { LLConversationItem* participant_model = dynamic_cast(*current_participant_model); - if (participant_model) - { - addConversationViewParticipant(participant_model); - } + if (participant_model) + { + addConversationViewParticipant(participant_model); + } current_participant_model++; } } @@ -553,10 +626,10 @@ void LLFloaterIMSessionTab::addConversationViewParticipant(LLConversationItem* p // If not already present, create the participant view and attach it to the root, otherwise, just refresh it if (widget) { - if (update_view) - { - updateConversationViewParticipant(uuid); // overkill? - } + if (update_view) + { + updateConversationViewParticipant(uuid); // overkill? + } } else { @@ -606,11 +679,11 @@ void LLFloaterIMSessionTab::refreshConversation() { participants_uuids.push_back(widget_it->first); } - if (widget_it->second->getViewModelItem()) - { - widget_it->second->refresh(); - widget_it->second->setVisible(TRUE); - } + if (widget_it->second->getViewModelItem()) + { + widget_it->second->refresh(); + widget_it->second->setVisible(TRUE); + } ++widget_it; } if (is_ad_hoc || mIsP2PChat) @@ -666,7 +739,7 @@ void LLFloaterIMSessionTab::refreshConversation() // Copied from LLFloaterIMContainer::createConversationViewParticipant(). Refactor opportunity! LLConversationViewParticipant* LLFloaterIMSessionTab::createConversationViewParticipant(LLConversationItem* item) { - LLRect panel_rect = mParticipantListPanel->getRect(); + LLRect panel_rect = mParticipantListPanel->getRect(); LLConversationViewParticipant::Params params; params.name = item->getDisplayName(); @@ -794,7 +867,7 @@ void LLFloaterIMSessionTab::hideAllStandardButtons() void LLFloaterIMSessionTab::updateHeaderAndToolbar() { // prevent start conversation before its container - LLFloaterIMContainer::getInstance(); + LLFloaterIMContainer::getInstance(); bool is_not_torn_off = !checkIfTornOff(); if (is_not_torn_off) @@ -811,12 +884,12 @@ void LLFloaterIMSessionTab::updateHeaderAndToolbar() && !mIsP2PChat; mParticipantListAndHistoryStack->collapsePanel(mParticipantListPanel, !is_participant_list_visible); - mParticipantListPanel->setVisible(is_participant_list_visible); + mParticipantListPanel->setVisible(is_participant_list_visible); // Display collapse image (<<) if the floater is hosted // or if it is torn off but has an open control panel. bool is_expanded = is_not_torn_off || is_participant_list_visible; - + mExpandCollapseBtn->setImageOverlay(getString(is_expanded ? "collapse_icon" : "expand_icon")); mExpandCollapseBtn->setToolTip( is_not_torn_off? @@ -845,10 +918,10 @@ void LLFloaterIMSessionTab::updateHeaderAndToolbar() void LLFloaterIMSessionTab::forceReshape() { - LLRect floater_rect = getRect(); - reshape(llmax(floater_rect.getWidth(), this->getMinWidth()), - llmax(floater_rect.getHeight(), this->getMinHeight()), - true); + LLRect floater_rect = getRect(); + reshape(llmax(floater_rect.getWidth(), this->getMinWidth()), + llmax(floater_rect.getHeight(), this->getMinHeight()), + true); } @@ -874,7 +947,7 @@ void LLFloaterIMSessionTab::processChatHistoryStyleUpdate(bool clean_messages/* LLFloaterIMNearbyChat* nearby_chat = LLFloaterReg::findTypedInstance("nearby_chat"); if (nearby_chat) { - nearby_chat->reloadMessages(clean_messages); + nearby_chat->reloadMessages(clean_messages); } } @@ -920,15 +993,15 @@ void LLFloaterIMSessionTab::onSlide(LLFloaterIMSessionTab* self) { if (!self->mIsP2PChat) { - // The state must toggle the collapsed state of the panel - should_be_expanded = self->mParticipantListPanel->isCollapsed(); + // The state must toggle the collapsed state of the panel + should_be_expanded = self->mParticipantListPanel->isCollapsed(); // Update the expand/collapse flag of the participant list panel and save it - gSavedSettings.setBOOL("IMShowControlPanel", should_be_expanded); - self->mIsParticipantListExpanded = should_be_expanded; - - // Refresh for immediate feedback - self->refreshConversation(); + gSavedSettings.setBOOL("IMShowControlPanel", should_be_expanded); + self->mIsParticipantListExpanded = should_be_expanded; + + // Refresh for immediate feedback + self->refreshConversation(); } } @@ -965,12 +1038,12 @@ void LLFloaterIMSessionTab::reshapeFloater(bool collapse) + mChatLayoutPanel->getRect().getHeight() - mChatLayoutPanelHeight + 2; floater_rect.mTop -= height; - setResizeLimits(getMinWidth(), floater_rect.getHeight()); + setResizeLimits(getMinWidth(), floater_rect.getHeight()); } else { floater_rect.mTop = floater_rect.mBottom + mFloaterHeight; - setResizeLimits(getMinWidth(), mMinFloaterHeight); + setResizeLimits(getMinWidth(), mMinFloaterHeight); } enableResizeCtrls(true, true, !collapse); @@ -995,7 +1068,7 @@ void LLFloaterIMSessionTab::restoreFloater() setShape(floater_rect, true); mBodyStack->updateLayout(); mExpandCollapseLineBtn->setImageOverlay(getString("expandline_icon")); - setResizeLimits(getMinWidth(), mMinFloaterHeight); + setResizeLimits(getMinWidth(), mMinFloaterHeight); setMessagePaneExpanded(true); saveCollapsedState(); mInputEditor->enableSingleLineMode(false); @@ -1021,8 +1094,8 @@ void LLFloaterIMSessionTab::onTearOffClicked() { restoreFloater(); setFollows(isTornOff()? FOLLOWS_ALL : FOLLOWS_NONE); - mSaveRect = isTornOff(); - initRectControl(); + mSaveRect = isTornOff(); + initRectControl(); LLFloater::onClickTearOff(this); LLFloaterIMContainer* container = LLFloaterReg::findTypedInstance("im_container"); @@ -1112,8 +1185,8 @@ bool LLFloaterIMSessionTab::checkIfTornOff() void LLFloaterIMSessionTab::doToSelected(const LLSD& userdata) { // Get the list of selected items in the tab - std::string command = userdata.asString(); - uuid_vec_t selected_uuids; + std::string command = userdata.asString(); + uuid_vec_t selected_uuids; getSelectedUUIDs(selected_uuids); // Perform the command (IM, profile, etc...) on the list using the general conversation container method @@ -1125,8 +1198,8 @@ void LLFloaterIMSessionTab::doToSelected(const LLSD& userdata) bool LLFloaterIMSessionTab::enableContextMenuItem(const LLSD& userdata) { // Get the list of selected items in the tab - std::string command = userdata.asString(); - uuid_vec_t selected_uuids; + std::string command = userdata.asString(); + uuid_vec_t selected_uuids; getSelectedUUIDs(selected_uuids); // Perform the item enable test on the list using the general conversation container method @@ -1137,8 +1210,8 @@ bool LLFloaterIMSessionTab::enableContextMenuItem(const LLSD& userdata) bool LLFloaterIMSessionTab::checkContextMenuItem(const LLSD& userdata) { // Get the list of selected items in the tab - std::string command = userdata.asString(); - uuid_vec_t selected_uuids; + std::string command = userdata.asString(); + uuid_vec_t selected_uuids; getSelectedUUIDs(selected_uuids); // Perform the item check on the list using the general conversation container method @@ -1148,19 +1221,19 @@ bool LLFloaterIMSessionTab::checkContextMenuItem(const LLSD& userdata) void LLFloaterIMSessionTab::getSelectedUUIDs(uuid_vec_t& selected_uuids) { - const std::set selected_items = mConversationsRoot->getSelectionList(); + const std::set selected_items = mConversationsRoot->getSelectionList(); - std::set::const_iterator it = selected_items.begin(); - const std::set::const_iterator it_end = selected_items.end(); + std::set::const_iterator it = selected_items.begin(); + const std::set::const_iterator it_end = selected_items.end(); - for (; it != it_end; ++it) - { - LLConversationItem* conversation_item = static_cast((*it)->getViewModelItem()); - if (conversation_item) - { - selected_uuids.push_back(conversation_item->getUUID()); - } - } + for (; it != it_end; ++it) + { + LLConversationItem* conversation_item = static_cast((*it)->getViewModelItem()); + if (conversation_item) + { + selected_uuids.push_back(conversation_item->getUUID()); + } + } } LLConversationItem* LLFloaterIMSessionTab::getCurSelectedViewModelItem() @@ -1168,8 +1241,8 @@ LLConversationItem* LLFloaterIMSessionTab::getCurSelectedViewModelItem() LLConversationItem *conversationItem = NULL; if(mConversationsRoot && - mConversationsRoot->getCurSelectedItem() && - mConversationsRoot->getCurSelectedItem()->getViewModelItem()) + mConversationsRoot->getCurSelectedItem() && + mConversationsRoot->getCurSelectedItem()->getViewModelItem()) { conversationItem = static_cast(mConversationsRoot->getCurSelectedItem()->getViewModelItem()) ; } diff --git a/indra/newview/llfloaterimsessiontab.h b/indra/newview/llfloaterimsessiontab.h index 7babc92897..5f8ba44e48 100644 --- a/indra/newview/llfloaterimsessiontab.h +++ b/indra/newview/llfloaterimsessiontab.h @@ -41,10 +41,12 @@ class LLPanelChatControlPanel; class LLChatEntry; class LLChatHistory; +class LLPanelEmojiComplete; class LLFloaterIMSessionTab : public LLTransientDockableFloater { + using super = LLTransientDockableFloater; public: LOG_CLASS(LLFloaterIMSessionTab); @@ -68,9 +70,8 @@ public: bool isHostAttached() {return mIsHostAttached;} void setHostAttached(bool is_attached) {mIsHostAttached = is_attached;} - static LLFloaterIMSessionTab* findConversation(const LLUUID& uuid); - static LLFloaterIMSessionTab* getConversation(const LLUUID& uuid); - + static LLFloaterIMSessionTab* findConversation(const LLUUID& uuid); + static LLFloaterIMSessionTab* getConversation(const LLUUID& uuid); bool isNearbyChat() {return mIsNearbyChat;} @@ -80,6 +81,7 @@ public: /*virtual*/ void draw(); /*virtual*/ void setVisible(BOOL visible); /*virtual*/ void setFocus(BOOL focus); + /*virtual*/ void closeFloater(bool app_quitting = false); // Handle the left hand participant list widgets void addConversationViewParticipant(LLConversationItem* item, bool update_view = true); @@ -136,8 +138,8 @@ protected: virtual void enableDisableCallBtn(); // process focus events to set a currently active session - /* virtual */ void onFocusLost(); /* virtual */ void onFocusReceived(); + /* virtual */ void onFocusLost(); // prepare chat's params and out one message to chatHistory void appendMessage(const LLChat& chat, const LLSD& args = LLSD()); @@ -152,8 +154,7 @@ protected: bool mMessagePaneExpanded; bool mIsParticipantListExpanded; - S32 mMinFloaterHeight; - + S32 mMinFloaterHeight; LLIMModel::LLIMSession* mSession; @@ -168,33 +169,37 @@ protected: LLLayoutPanel* mContentPanel; LLLayoutPanel* mToolbarPanel; LLLayoutPanel* mInputButtonPanel; + LLLayoutPanel* mEmojiRecentPanel; + LLView* mEmojiRecentEmptyText; + LLPanelEmojiComplete* mEmojiRecentIconsCtrl; LLParticipantList* getParticipantList(); conversations_widgets_map mConversationsWidgets; LLConversationViewModel mConversationViewModel; LLFolderView* mConversationsRoot; LLScrollContainer* mScroller; - LLChatHistory* mChatHistory; + LLChatHistory* mChatHistory; LLChatEntry* mInputEditor; - LLLayoutPanel * mChatLayoutPanel; - LLLayoutStack * mInputPanels; + LLLayoutPanel* mChatLayoutPanel; + LLLayoutStack* mInputPanels; LLButton* mExpandCollapseLineBtn; LLButton* mExpandCollapseBtn; LLButton* mTearOffBtn; - LLButton* mEmojiBtn; + LLButton* mEmojiRecentPanelToggleBtn; + LLButton* mEmojiPickerToggleBtn; LLButton* mCloseBtn; LLButton* mGearBtn; LLButton* mAddBtn; - LLButton* mVoiceButton; + LLButton* mVoiceButton; private: // Handling selection and contextual menu - void doToSelected(const LLSD& userdata); - bool enableContextMenuItem(const LLSD& userdata); - bool checkContextMenuItem(const LLSD& userdata); + void doToSelected(const LLSD& userdata); + bool enableContextMenuItem(const LLSD& userdata); + bool checkContextMenuItem(const LLSD& userdata); - void getSelectedUUIDs(uuid_vec_t& selected_uuids); + void getSelectedUUIDs(uuid_vec_t& selected_uuids); /// Refreshes the floater at a constant rate. virtual void refresh() = 0; @@ -208,13 +213,16 @@ private: void onInputEditorClicked(); - static void onEmojiPanelBtnClicked(LLFloaterIMSessionTab* self); + static void onEmojiRecentPanelToggleBtnClicked(LLFloaterIMSessionTab* self); + static void onEmojiPickerToggleBtnClicked(LLFloaterIMSessionTab* self); + void onEmojiRecentPanelOpening(); + void onRecentEmojiPicked(const LLSD& value); void onEmojiPicked(llwchar emoji); void onEmojiPickerClosed(); bool checkIfTornOff(); - bool mIsHostAttached; - bool mHasVisibleBeenInitialized; + bool mIsHostAttached; + bool mHasVisibleBeenInitialized; LLTimer* mRefreshTimer; ///< Defines the rate at which refresh() is called. diff --git a/indra/newview/skins/default/xui/en/floater_im_session.xml b/indra/newview/skins/default/xui/en/floater_im_session.xml index fc54710941..56965ba7bc 100644 --- a/indra/newview/skins/default/xui/en/floater_im_session.xml +++ b/indra/newview/skins/default/xui/en/floater_im_session.xml @@ -300,8 +300,8 @@ right="-30" wrap="true" />