diff options
Diffstat (limited to 'indra/newview')
24 files changed, 713 insertions, 788 deletions
diff --git a/indra/newview/llavataractions.cpp b/indra/newview/llavataractions.cpp index ac14ec2cc0..aa626a9a30 100755 --- a/indra/newview/llavataractions.cpp +++ b/indra/newview/llavataractions.cpp @@ -1024,7 +1024,6 @@ void LLAvatarActions::requestFriendship(const LLUUID& target_id, const std::stri LLSD payload; payload["from_id"] = target_id; - payload["SUPPRESS_TOAST"] = true; LLNotificationsUtil::add("FriendshipOffered", args, payload); } diff --git a/indra/newview/llcallingcard.cpp b/indra/newview/llcallingcard.cpp index 0d55c4429a..60d60abd45 100644 --- a/indra/newview/llcallingcard.cpp +++ b/indra/newview/llcallingcard.cpp @@ -54,6 +54,7 @@ #include "llresmgr.h" #include "llslurl.h" #include "llimview.h" +#include "lltrans.h" #include "llviewercontrol.h" #include "llviewernetwork.h" #include "llviewerobjectlist.h" @@ -723,12 +724,13 @@ static void on_avatar_name_cache_notify(const LLUUID& agent_id, // Use display name only because this user is your friend LLSD args; args["NAME"] = av_name.mDisplayName; + args["STATUS"] = online ? LLTrans::getString("OnlineStatus") : LLTrans::getString("OfflineStatus"); LLNotificationPtr notification; if (online) { notification = - LLNotificationsUtil::add("FriendOnline", + LLNotificationsUtil::add("FriendOnlineOffline", args, payload.with("respond_on_mousedown", TRUE), boost::bind(&LLAvatarActions::startIM, agent_id)); @@ -736,7 +738,7 @@ static void on_avatar_name_cache_notify(const LLUUID& agent_id, else { notification = - LLNotificationsUtil::add("FriendOffline", args, payload); + LLNotificationsUtil::add("FriendOnlineOffline", args, payload); } // If there's an open IM session with this agent, send a notification there too. diff --git a/indra/newview/llchathistory.cpp b/indra/newview/llchathistory.cpp index 3214c95600..c514261b60 100644 --- a/indra/newview/llchathistory.cpp +++ b/indra/newview/llchathistory.cpp @@ -786,12 +786,12 @@ void LLChatHistory::appendMessage(const LLChat& chat, const LLSD &args, const LL // timestams showing if (args["show_time"].asBoolean()) { - if (!message_from_log) - { - LLColor4 timestamp_color = LLUIColorTable::instance().getColor("ChatTimestampColor"); - timestamp_style.color(timestamp_color); - timestamp_style.readonly_color(timestamp_color); - } + if (!message_from_log) + { + LLColor4 timestamp_color = LLUIColorTable::instance().getColor("ChatTimestampColor"); + timestamp_style.color(timestamp_color); + timestamp_style.readonly_color(timestamp_color); + } mEditor->appendText("[" + chat.mTimeStr + "] ", prependNewLineState, timestamp_style); prependNewLineState = false; } @@ -817,7 +817,7 @@ void LLChatHistory::appendMessage(const LLChat& chat, const LLSD &args, const LL mEditor->appendText(chat.mFromName + delimiter, prependNewLineState, link_params); prependNewLineState = false; } - else if (chat.mFromName != SYSTEM_FROM && chat.mFromID.notNull() && !message_from_log) + else if ( chat.mFromName != SYSTEM_FROM && chat.mFromID.notNull() && !message_from_log) { LLStyle::Params link_params(style_params); link_params.overwriteFrom(LLStyleMap::instance().lookupAgent(chat.mFromID)); @@ -831,7 +831,7 @@ void LLChatHistory::appendMessage(const LLChat& chat, const LLSD &args, const LL } else { - // Add link to avatar's inspector and delimiter to message. + // Add link to avatar's inspector and delimiter to message. mEditor->appendText(std::string(link_params.link_href) + delimiter, prependNewLineState, link_params); prependNewLineState = false; @@ -903,35 +903,7 @@ void LLChatHistory::appendMessage(const LLChat& chat, const LLSD &args, const LL if (notification != NULL) { LLIMToastNotifyPanel* notify_box = new LLIMToastNotifyPanel( - notification, chat.mSessionID, LLRect::null, !use_plain_text_chat_history); - //we can't set follows in xml since it broke toasts behavior - notify_box->setFollowsLeft(); - notify_box->setFollowsRight(); - notify_box->setFollowsTop(); - - ctrl_list_t ctrls = notify_box->getControlPanel()->getCtrlList(); - S32 offset = 0; - // Children were added by addChild() which uses push_front to insert them into list, - // so to get buttons in correct order reverse iterator is used (EXT-5906) - for (ctrl_list_t::reverse_iterator it = ctrls.rbegin(); it != ctrls.rend(); it++) - { - LLButton * button = dynamic_cast<LLButton*> (*it); - if (button != NULL) - { - button->setOrigin( offset, - button->getRect().mBottom); - button->setLeftHPad(2 * HPAD); - button->setRightHPad(2 * HPAD); - // set zero width before perform autoResize() - button->setRect(LLRect(button->getRect().mLeft, - button->getRect().mTop, button->getRect().mLeft, - button->getRect().mBottom)); - button->setAutoResize(true); - button->autoResize(); - offset += HPAD + button->getRect().getWidth(); - button->setFollowsNone(); - } - } + notification, chat.mSessionID, LLRect::null, !use_plain_text_chat_history, mEditor); //Prepare the rect for the view LLRect target_rect = mEditor->getDocumentView()->getRect(); diff --git a/indra/newview/llchatitemscontainerctrl.cpp b/indra/newview/llchatitemscontainerctrl.cpp index 9a84280f25..7477fbd656 100644 --- a/indra/newview/llchatitemscontainerctrl.cpp +++ b/indra/newview/llchatitemscontainerctrl.cpp @@ -372,7 +372,6 @@ void LLNearbyChatToastPanel::draw() } mIsDirty = false; } - LLToastPanelBase::draw(); } diff --git a/indra/newview/llchatitemscontainerctrl.h b/indra/newview/llchatitemscontainerctrl.h index 1d700dcede..89b0c4f37a 100644 --- a/indra/newview/llchatitemscontainerctrl.h +++ b/indra/newview/llchatitemscontainerctrl.h @@ -40,7 +40,7 @@ typedef enum e_show_item_header CHATITEMHEADER_SHOW_BOTH } EShowItemHeader; -class LLNearbyChatToastPanel: public LLToastPanelBase +class LLNearbyChatToastPanel : public LLPanel { protected: LLNearbyChatToastPanel() diff --git a/indra/newview/llimfloater.cpp b/indra/newview/llimfloater.cpp index 97f59f9a15..cd795fcfc7 100644 --- a/indra/newview/llimfloater.cpp +++ b/indra/newview/llimfloater.cpp @@ -57,6 +57,7 @@ #include "llrootview.h" #include "llspeakers.h" #include "llviewerchat.h" +#include "llnotificationmanager.h" LLIMFloater::LLIMFloater(const LLUUID& session_id) : LLTransientDockableFloater(NULL, true, session_id), @@ -96,7 +97,7 @@ LLIMFloater::LLIMFloater(const LLUUID& session_id) case IM_SESSION_GROUP_START: mFactoryMap["panel_im_control_panel"] = LLCallbackMap(createPanelGroupControl, this); break; - case IM_SESSION_INVITE: + case IM_SESSION_INVITE: if (gAgent.isInGroup(mSessionID)) { mFactoryMap["panel_im_control_panel"] = LLCallbackMap(createPanelGroupControl, this); @@ -168,7 +169,7 @@ void LLIMFloater::onIMSessionMenuItemClicked(const LLSD& userdata) void LLIMFloater::onFocusLost() { LLIMModel::getInstance()->resetActiveSessionID(); - + LLChicletBar::getInstance()->getChicletPanel()->setChicletToggleState(mSessionID, false); } @@ -220,7 +221,7 @@ void LLIMFloater::newIMCallback(const LLSD& data) LLIMFloater* floater = LLFloaterReg::findTypedInstance<LLIMFloater>("impanel", session_id); if (floater == NULL) return; - // update if visible, otherwise will be updated when opened + // update if visible, otherwise will be updated when opened if (floater->getVisible()) { floater->updateMessages(); @@ -235,7 +236,7 @@ void LLIMFloater::onVisibilityChange(const LLSD& new_visibility) LLVoiceChannel* voice_channel = LLIMModel::getInstance()->getVoiceChannel(mSessionID); if (visible && voice_channel && - voice_channel->getState() == LLVoiceChannel::STATE_CONNECTED) + voice_channel->getState() == LLVoiceChannel::STATE_CONNECTED) { LLFloaterReg::showInstance("voice_call", mSessionID); } @@ -254,9 +255,9 @@ void LLIMFloater::onSendMsg( LLUICtrl* ctrl, void* userdata ) void LLIMFloater::sendMsg() { - if (!gAgent.isGodlike() - && (mDialog == IM_NOTHING_SPECIAL) - && mOtherParticipantUUID.isNull()) + if (!gAgent.isGodlike() + && (mDialog == IM_NOTHING_SPECIAL) + && mOtherParticipantUUID.isNull()) { llinfos << "Cannot send IM to everyone unless you're a god." << llendl; return; @@ -265,12 +266,12 @@ void LLIMFloater::sendMsg() if (mInputEditor) { LLWString text = mInputEditor->getConvertedText(); - if (!text.empty()) + if(!text.empty()) { // Truncate and convert to UTF8 for transport std::string utf8_text = wstring_to_utf8str(text); utf8_text = utf8str_truncate(utf8_text, MAX_MSG_BUF_SIZE - 1); - + if (mSessionInitialized) { LLIMModel::sendMessage(utf8_text, mSessionID, mOtherParticipantUUID, mDialog); @@ -319,8 +320,8 @@ BOOL LLIMFloater::postBuild() if (mControlPanel) { - mControlPanel->setSessionId(mSessionID); - mControlPanel->getParent()->setVisible(gSavedSettings.getBOOL("IMShowControlPanel")); + mControlPanel->setSessionId(mSessionID); + mControlPanel->getParent()->setVisible(gSavedSettings.getBOOL("IMShowControlPanel")); mExpandCollapseBtn->setImageOverlay( getString(mControlPanel->getParent()->getVisible() ? "collapse_icon" : "expand_icon")); @@ -340,8 +341,8 @@ BOOL LLIMFloater::postBuild() mInputEditor->setEnableLineHistory(TRUE); LLFontGL* font = LLViewerChat::getChatFont(); - mInputEditor->setFont(font); - + mInputEditor->setFont(font); + mInputEditor->setFocusReceivedCallback( boost::bind(onInputEditorFocusReceived, _1, this) ); mInputEditor->setFocusLostCallback( boost::bind(onInputEditorFocusLost, _1, this) ); mInputEditor->setKeystrokeCallback( onInputEditorKeystroke, this ); @@ -351,7 +352,7 @@ BOOL LLIMFloater::postBuild() mInputEditor->setPassDelete( TRUE ); childSetCommitCallback("chat_editor", onSendMsg, this); - + mChatHistory = getChild<LLChatHistory>("chat_history"); setDocked(true); @@ -369,15 +370,15 @@ BOOL LLIMFloater::postBuild() { // look up display name for window title LLAvatarNameCache::get(mSession->mOtherParticipantID, - boost::bind(&LLIMFloater::onAvatarNameCache, - this, _1, _2)); + boost::bind(&LLIMFloater::onAvatarNameCache, + this, _1, _2)); } else { std::string session_name(LLIMModel::instance().getName(mSessionID)); updateSessionName(session_name, session_name); } - + childSetAction("voice_call_btn", boost::bind(&LLIMFloater::onCallButtonClicked, this)); LLVoiceClient::getInstance()->addObserver(this); @@ -385,7 +386,7 @@ BOOL LLIMFloater::postBuild() //*TODO if session is not initialized yet, add some sort of a warning message like "starting session...blablabla" //see LLFloaterIMPanel for how it is done (IB) - if (isChatMultiTab()) + if(isChatMultiTab()) { return LLFloater::postBuild(); } @@ -484,14 +485,14 @@ void LLIMFloater::onVoiceChannelStateChanged( } void LLIMFloater::updateSessionName(const std::string& ui_title, - const std::string& ui_label) + const std::string& ui_label) { mInputEditor->setLabel(LLTrans::getString("IM_to_label") + " " + ui_label); - setTitle(ui_title); + setTitle(ui_title); } void LLIMFloater::onAvatarNameCache(const LLUUID& agent_id, - const LLAvatarName& av_name) + const LLAvatarName& av_name) { // Use display name only for labels, as the extended name will be in the // floater title @@ -506,7 +507,7 @@ void LLIMFloater::draw() if ( mMeTyping ) { // Time out if user hasn't typed for a while. - if (mTypingTimeoutTimer.getElapsedTimeF32() > LLAgent::TYPING_TIMEOUT_SECS) + if ( mTypingTimeoutTimer.getElapsedTimeF32() > LLAgent::TYPING_TIMEOUT_SECS ) { setTyping(false); } @@ -518,7 +519,7 @@ void LLIMFloater::draw() // static void* LLIMFloater::createPanelGroupControl(void* userdata) { - LLIMFloater *self = (LLIMFloater*) userdata; + LLIMFloater *self = (LLIMFloater*)userdata; self->mControlPanel = new LLPanelGroupControlPanel(self->mSessionID); self->mControlPanel->setXMLFilename("panel_group_control_panel.xml"); return self->mControlPanel; @@ -527,7 +528,7 @@ void* LLIMFloater::createPanelGroupControl(void* userdata) // static void* LLIMFloater::createPanelAdHocControl(void* userdata) { - LLIMFloater *self = (LLIMFloater*) userdata; + LLIMFloater *self = (LLIMFloater*)userdata; self->mControlPanel = new LLPanelAdHocControlPanel(self->mSessionID); self->mControlPanel->setXMLFilename("panel_adhoc_control_panel.xml"); return self->mControlPanel; @@ -565,12 +566,12 @@ LLIMFloater* LLIMFloater::show(const LLUUID& session_id) if (!gIMMgr->hasSession(session_id)) return NULL; - if (!isChatMultiTab()) + if(!isChatMultiTab()) { //hide all LLFloaterReg::const_instance_list_t& inst_list = LLFloaterReg::getFloaterList("impanel"); for (LLFloaterReg::const_instance_list_t::const_iterator iter = inst_list.begin(); - iter != inst_list.end(); ++iter) + iter != inst_list.end(); ++iter) { LLIMFloater* floater = dynamic_cast<LLIMFloater*>(*iter); if (floater && floater->isDocked()) @@ -586,7 +587,7 @@ LLIMFloater* LLIMFloater::show(const LLUUID& session_id) if (!floater) return NULL; - if (isChatMultiTab()) + if(isChatMultiTab()) { LLIMFloaterContainer* floater_container = LLIMFloaterContainer::getInstance(); @@ -596,7 +597,7 @@ LLIMFloater* LLIMFloater::show(const LLUUID& session_id) // LLTabContainer::eInsertionPoint i_pt = user_initiated ? LLTabContainer::RIGHT_OF_CURRENT : LLTabContainer::END; // TODO: mantipov: use LLTabContainer::RIGHT_OF_CURRENT if it exists LLTabContainer::eInsertionPoint i_pt = LLTabContainer::END; - + if (floater_container) { floater_container->addFloater(floater, TRUE, i_pt); @@ -639,16 +640,16 @@ void LLIMFloater::setDocked(bool docked, bool pop_on_undock) { // update notification channel state LLNotificationsUI::LLScreenChannel* channel = static_cast<LLNotificationsUI::LLScreenChannel*> - (LLNotificationsUI::LLChannelManager::getInstance()-> - findChannelByID(LLUUID(gSavedSettings.getString("NotificationChannelUUID")))); - - if (!isChatMultiTab()) + (LLNotificationsUI::LLChannelManager::getInstance()-> + findChannelByID(LLUUID(gSavedSettings.getString("NotificationChannelUUID")))); + + if(!isChatMultiTab()) { LLTransientDockableFloater::setDocked(docked, pop_on_undock); } // update notification channel state - if (channel) + if(channel) { channel->updateShowToastsState(); channel->redrawToasts(); @@ -658,12 +659,12 @@ void LLIMFloater::setDocked(bool docked, bool pop_on_undock) void LLIMFloater::setVisible(BOOL visible) { LLNotificationsUI::LLScreenChannel* channel = static_cast<LLNotificationsUI::LLScreenChannel*> - (LLNotificationsUI::LLChannelManager::getInstance()-> - findChannelByID(LLUUID(gSavedSettings.getString("NotificationChannelUUID")))); + (LLNotificationsUI::LLChannelManager::getInstance()-> + findChannelByID(LLUUID(gSavedSettings.getString("NotificationChannelUUID")))); LLTransientDockableFloater::setVisible(visible); // update notification channel state - if (channel) + if(channel) { channel->updateShowToastsState(); channel->redrawToasts(); @@ -684,10 +685,10 @@ void LLIMFloater::setVisible(BOOL visible) } } - if (!visible) + if(!visible) { LLIMChiclet* chiclet = LLChicletBar::getInstance()->getChicletPanel()->findChiclet<LLIMChiclet>(mSessionID); - if (chiclet) + if(chiclet) { chiclet->setToggleState(false); } @@ -696,14 +697,14 @@ void LLIMFloater::setVisible(BOOL visible) BOOL LLIMFloater::getVisible() { - if (isChatMultiTab()) + if(isChatMultiTab()) { LLIMFloaterContainer* im_container = LLIMFloaterContainer::getInstance(); - + // Treat inactive floater as invisible. bool is_active = im_container->getActiveFloater() == this; - + //torn off floater is always inactive if (!is_active && getHost() != im_container) { @@ -723,7 +724,7 @@ BOOL LLIMFloater::getVisible() //static bool LLIMFloater::toggle(const LLUUID& session_id) { - if (!isChatMultiTab()) + if(!isChatMultiTab()) { LLIMFloater* floater = LLFloaterReg::findTypedInstance<LLIMFloater>( "impanel", session_id); @@ -734,7 +735,7 @@ bool LLIMFloater::toggle(const LLUUID& session_id) floater->setVisible(false); return false; } - else if (floater && (!floater->isDocked() || floater->getVisible() && !floater->hasFocus())) + else if(floater && (!floater->isDocked() || floater->getVisible() && !floater->hasFocus())) { floater->setVisible(TRUE); floater->setFocus(TRUE); @@ -770,25 +771,25 @@ void LLIMFloater::sessionInitReplyReceived(const LLUUID& im_session_id) setKey(im_session_id); if (mControlPanel) { - mControlPanel->setSessionId(im_session_id); - } + mControlPanel->setSessionId(im_session_id); + } boundVoiceChannel(); mSession = LLIMModel::getInstance()->findIMSession(mSessionID); mIsP2PChat = mSession && mSession->isP2PSessionType(); } - + //*TODO here we should remove "starting session..." warning message if we added it in postBuild() (IB) //need to send delayed messaged collected while waiting for session initialization if (!mQueuedMsgsForInit.size()) return; LLSD::array_iterator iter; - for (iter = mQueuedMsgsForInit.beginArray(); + for ( iter = mQueuedMsgsForInit.beginArray(); iter != mQueuedMsgsForInit.endArray(); ++iter) { LLIMModel::sendMessage(iter->asString(), mSessionID, - mOtherParticipantUUID, mDialog); + mOtherParticipantUUID, mDialog); } } @@ -850,8 +851,8 @@ void LLIMFloater::updateMessages() { // remove embedded notification from channel LLNotificationsUI::LLScreenChannel* channel = static_cast<LLNotificationsUI::LLScreenChannel*> - (LLNotificationsUI::LLChannelManager::getInstance()-> - findChannelByID(LLUUID(gSavedSettings.getString("NotificationChannelUUID")))); + (LLNotificationsUI::LLChannelManager::getInstance()-> + findChannelByID(LLUUID(gSavedSettings.getString("NotificationChannelUUID")))); if (getVisible()) { // toast will be automatically closed since it is not storable toast @@ -869,7 +870,7 @@ void LLIMFloater::updateMessages() { chat.mText = message; } - + appendMessage(chat); mLastMessageIndex = msg["index"].asInteger(); @@ -877,16 +878,16 @@ void LLIMFloater::updateMessages() if (chat.mNotifId.notNull() && LLNotificationsUtil::find(chat.mNotifId) != NULL) { if (++iter == iter_end) - { - break; - } - else - { - mLastMessageIndex++; - } - } - } - } + { + break; + } + else + { + mLastMessageIndex++; + } + } + } + } } void LLIMFloater::reloadMessages() @@ -897,15 +898,15 @@ void LLIMFloater::reloadMessages() } // static -void LLIMFloater::onInputEditorFocusReceived(LLFocusableElement* caller, void* userdata) +void LLIMFloater::onInputEditorFocusReceived( LLFocusableElement* caller, void* userdata ) { - LLIMFloater* self = (LLIMFloater*) userdata; + LLIMFloater* self= (LLIMFloater*) userdata; // Allow enabling the LLIMFloater input editor only if session can accept text LLIMModel::LLIMSession* im_session = - LLIMModel::instance().findIMSession(self->mSessionID); + LLIMModel::instance().findIMSession(self->mSessionID); //TODO: While disabled lllineeditor can receive focus we need to check if it is enabled (EK) - if (im_session && im_session->mTextIMPossible && self->mInputEditor->getEnabled()) + if( im_session && im_session->mTextIMPossible && self->mInputEditor->getEnabled()) { //in disconnected state IM input editor should be disabled self->mInputEditor->setEnabled(!gDisconnected); @@ -922,7 +923,7 @@ void LLIMFloater::onInputEditorFocusLost(LLFocusableElement* caller, void* userd // static void LLIMFloater::onInputEditorKeystroke(LLLineEditor* caller, void* userdata) { - LLIMFloater* self = (LLIMFloater*) userdata; + LLIMFloater* self = (LLIMFloater*)userdata; std::string text = self->mInputEditor->getText(); if (!text.empty()) { @@ -937,13 +938,13 @@ void LLIMFloater::onInputEditorKeystroke(LLLineEditor* caller, void* userdata) void LLIMFloater::setTyping(bool typing) { - if (typing) + if ( typing ) { // Started or proceeded typing, reset the typing timeout timer mTypingTimeoutTimer.reset(); } - if (mMeTyping != typing) + if ( mMeTyping != typing ) { // Typing state is changed mMeTyping = typing; @@ -955,11 +956,11 @@ void LLIMFloater::setTyping(bool typing) // Don't want to send typing indicators to multiple people, potentially too // much network traffic. Only send in person-to-person IMs. - if (mShouldSendTypingState && mDialog == IM_NOTHING_SPECIAL) + if ( mShouldSendTypingState && mDialog == IM_NOTHING_SPECIAL ) { - if (mMeTyping) + if ( mMeTyping ) { - if (mTypingTimer.getElapsedTimeF32() > 1.f) + if ( mTypingTimer.getElapsedTimeF32() > 1.f ) { // Still typing, send 'start typing' notification LLIMModel::instance().sendTypingState(mSessionID, @@ -984,7 +985,7 @@ void LLIMFloater::setTyping(bool typing) void LLIMFloater::processIMTyping(const LLIMInfo* im_info, BOOL typing) { - if (typing) + if ( typing ) { // other user started typing addTypingIndicator(im_info); @@ -1001,7 +1002,7 @@ void LLIMFloater::processAgentListUpdates(const LLSD& body) if (!body.isMap()) return; - if (body.has("agent_updates") && body["agent_updates"].isMap()) + if ( body.has("agent_updates") && body["agent_updates"].isMap() ) { LLSD agent_data = body["agent_updates"].get(gAgentID.asString()); if (agent_data.isMap() && agent_data.has("info")) @@ -1010,7 +1011,7 @@ void LLIMFloater::processAgentListUpdates(const LLSD& body) if (agent_info.has("mutes")) { - BOOL moderator_muted_text = agent_info["mutes"]["text"].asBoolean(); + BOOL moderator_muted_text = agent_info["mutes"]["text"].asBoolean(); mInputEditor->setEnabled(!moderator_muted_text); std::string label; if (moderator_muted_text) @@ -1031,7 +1032,7 @@ void LLIMFloater::processChatHistoryStyleUpdate() LLFontGL* font = LLViewerChat::getChatFont(); LLFloaterReg::const_instance_list_t& inst_list = LLFloaterReg::getFloaterList("impanel"); for (LLFloaterReg::const_instance_list_t::const_iterator iter = inst_list.begin(); - iter != inst_list.end(); ++iter) + iter != inst_list.end(); ++iter) { LLIMFloater* floater = dynamic_cast<LLIMFloater*>(*iter); if (floater) @@ -1045,8 +1046,8 @@ void LLIMFloater::processChatHistoryStyleUpdate() void LLIMFloater::processSessionUpdate(const LLSD& session_update) { // *TODO : verify following code when moderated mode will be implemented - if (false && session_update.has("moderated_mode") && - session_update["moderated_mode"].has("voice")) + if ( false && session_update.has("moderated_mode") && + session_update["moderated_mode"].has("voice") ) { BOOL voice_moderated = session_update["moderated_mode"]["voice"]; const std::string session_label = LLIMModel::instance().getName(mSessionID); @@ -1068,14 +1069,14 @@ void LLIMFloater::processSessionUpdate(const LLSD& session_update) } BOOL LLIMFloater::handleDragAndDrop(S32 x, S32 y, MASK mask, - BOOL drop, EDragAndDropType cargo_type, - void *cargo_data, EAcceptance *accept, - std::string& tooltip_msg) + BOOL drop, EDragAndDropType cargo_type, + void *cargo_data, EAcceptance *accept, + std::string& tooltip_msg) { if (mDialog == IM_NOTHING_SPECIAL) { LLToolDragAndDrop::handleGiveDragAndDrop(mOtherParticipantUUID, mSessionID, drop, - cargo_type, cargo_data, accept); + cargo_type, cargo_data, accept); } // handle case for dropping calling cards (and folders of calling cards) onto invitation panel for invites @@ -1085,14 +1086,14 @@ BOOL LLIMFloater::handleDragAndDrop(S32 x, S32 y, MASK mask, if (cargo_type == DAD_CALLINGCARD) { - if (dropCallingCard((LLInventoryItem*) cargo_data, drop)) + if (dropCallingCard((LLInventoryItem*)cargo_data, drop)) { *accept = ACCEPT_YES_MULTI; } } else if (cargo_type == DAD_CATEGORY) { - if (dropCategory((LLInventoryCategory*) cargo_data, drop)) + if (dropCategory((LLInventoryCategory*)cargo_data, drop)) { *accept = ACCEPT_YES_MULTI; } @@ -1104,9 +1105,9 @@ BOOL LLIMFloater::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL LLIMFloater::dropCallingCard(LLInventoryItem* item, BOOL drop) { BOOL rv = isInviteAllowed(); - if (rv && item && item->getCreatorUUID().notNull()) + if(rv && item && item->getCreatorUUID().notNull()) { - if (drop) + if(drop) { uuid_vec_t ids; ids.push_back(item->getCreatorUUID()); @@ -1124,26 +1125,26 @@ BOOL LLIMFloater::dropCallingCard(LLInventoryItem* item, BOOL drop) BOOL LLIMFloater::dropCategory(LLInventoryCategory* category, BOOL drop) { BOOL rv = isInviteAllowed(); - if (rv && category) + if(rv && category) { LLInventoryModel::cat_array_t cats; LLInventoryModel::item_array_t items; LLUniqueBuddyCollector buddies; gInventory.collectDescendentsIf(category->getUUID(), - cats, - items, - LLInventoryModel::EXCLUDE_TRASH, - buddies); + cats, + items, + LLInventoryModel::EXCLUDE_TRASH, + buddies); S32 count = items.count(); - if (count == 0) + if(count == 0) { rv = FALSE; } - else if (drop) + else if(drop) { uuid_vec_t ids; ids.reserve(count); - for (S32 i = 0; i < count; ++i) + for(S32 i = 0; i < count; ++i) { ids.push_back(items.get(i)->getCreatorUUID()); } @@ -1155,11 +1156,11 @@ BOOL LLIMFloater::dropCategory(LLInventoryCategory* category, BOOL drop) BOOL LLIMFloater::isInviteAllowed() const { - return ((IM_SESSION_CONFERENCE_START == mDialog) - || (IM_SESSION_INVITE == mDialog)); + return ( (IM_SESSION_CONFERENCE_START == mDialog) + || (IM_SESSION_INVITE == mDialog) ); } -class LLSessionInviteResponder: public LLHTTPClient::Responder +class LLSessionInviteResponder : public LLHTTPClient::Responder { public: LLSessionInviteResponder(const LLUUID& session_id) @@ -1187,7 +1188,7 @@ BOOL LLIMFloater::inviteToSession(const uuid_vec_t& ids) S32 count = ids.size(); - if (isInviteAllowed() && (count > 0)) + if( isInviteAllowed() && (count > 0) ) { llinfos << "LLIMFloater::inviteToSession() - inviting participants" << llendl; @@ -1204,8 +1205,8 @@ BOOL LLIMFloater::inviteToSession(const uuid_vec_t& ids) data["method"] = "invite"; data["session-id"] = mSessionID; LLHTTPClient::post( - url, - data, + url, + data, new LLSessionInviteResponder(mSessionID)); } else @@ -1223,17 +1224,17 @@ BOOL LLIMFloater::inviteToSession(const uuid_vec_t& ids) void LLIMFloater::addTypingIndicator(const LLIMInfo* im_info) { // We may have lost a "stop-typing" packet, don't add it twice - if (im_info && !mOtherTyping) + if ( im_info && !mOtherTyping ) { mOtherTyping = true; // Save and set new title mSavedTitle = getTitle(); - setTitle(mTypingStart); + setTitle (mTypingStart); // Update speaker LLIMSpeakerMgr* speaker_mgr = LLIMModel::getInstance()->getSpeakerManager(mSessionID); - if (speaker_mgr) + if ( speaker_mgr ) { speaker_mgr->setSpeakerTyping(im_info->mFromID, TRUE); } @@ -1242,18 +1243,18 @@ void LLIMFloater::addTypingIndicator(const LLIMInfo* im_info) void LLIMFloater::removeTypingIndicator(const LLIMInfo* im_info) { - if (mOtherTyping) + if ( mOtherTyping ) { mOtherTyping = false; // Revert the title to saved one setTitle(mSavedTitle); - if (im_info) + if ( im_info ) { // Update speaker LLIMSpeakerMgr* speaker_mgr = LLIMModel::getInstance()->getSpeakerManager(mSessionID); - if (speaker_mgr) + if ( speaker_mgr ) { speaker_mgr->setSpeakerTyping(im_info->mFromID, FALSE); } @@ -1276,8 +1277,8 @@ void LLIMFloater::updateHeaderAndToolbar() // Hide the standard header buttons in a docked IM floater. mButtons[i]->setVisible(false); - } } +} bool is_control_panel_visible = false; if (mControlPanel) @@ -1387,7 +1388,7 @@ void LLIMFloater::sRemoveTypingIndicator(const LLSD& data) floater->removeTypingIndicator(); } -void LLIMFloater::onIMChicletCreated(const LLUUID& session_id) +void LLIMFloater::onIMChicletCreated( const LLUUID& session_id ) { if (isChatMultiTab()) @@ -1406,11 +1407,11 @@ void LLIMFloater::onIMChicletCreated(const LLUUID& session_id) } -void LLIMFloater::onClickCloseBtn() +void LLIMFloater::onClickCloseBtn() { LLIMModel::LLIMSession* session = LLIMModel::instance().findIMSession( - mSessionID); + mSessionID); if (session == NULL) { diff --git a/indra/newview/llnearbychathandler.cpp b/indra/newview/llnearbychathandler.cpp index 4d9db01e0d..f26cc85019 100644 --- a/indra/newview/llnearbychathandler.cpp +++ b/indra/newview/llnearbychathandler.cpp @@ -1,6 +1,6 @@ /** * @file LLNearbyChatHandler.cpp - * @brief Nearby chat notification managment + * @brief Nearby chat chat managment * * $LicenseInfo:firstyear=2009&license=viewerlgpl$ * Second Life Viewer Source Code @@ -47,15 +47,17 @@ //add LLNearbyChatHandler to LLNotificationsUI namespace using namespace LLNotificationsUI; -//----------------------------------------------------------------------------------------------- -//LLNearbyChatScreenChannel -//----------------------------------------------------------------------------------------------- -LLToastPanelBase* createToastPanel() +static LLNearbyChatToastPanel* createToastPanel() { LLNearbyChatToastPanel* item = LLNearbyChatToastPanel::createInstance(); return item; } + +//----------------------------------------------------------------------------------------------- +//LLNearbyChatScreenChannel +//----------------------------------------------------------------------------------------------- + class LLNearbyChatScreenChannel: public LLScreenChannelBase { LOG_CLASS(LLNearbyChatScreenChannel); @@ -81,10 +83,10 @@ public: } } - void addNotification (LLSD& notification); + void addChat (LLSD& chat); void arrangeToasts (); - typedef boost::function<LLToastPanelBase* (void )> create_toast_panel_callback_t; + typedef boost::function<LLNearbyChatToastPanel* (void )> create_toast_panel_callback_t; void setCreatePanelCallback(create_toast_panel_callback_t value) { m_create_toast_panel_callback_t = value;} void onToastDestroyed (LLToast* toast, bool app_quitting); @@ -152,6 +154,8 @@ protected: bool mChannelRect; }; + + //----------------------------------------------------------------------------------------------- // LLNearbyChatToast //----------------------------------------------------------------------------------------------- @@ -255,7 +259,7 @@ void LLNearbyChatScreenChannel::updateToastFadingTime() bool LLNearbyChatScreenChannel::createPoolToast() { - LLToastPanelBase* panel= m_create_toast_panel_callback_t(); + LLNearbyChatToastPanel* panel= m_create_toast_panel_callback_t(); if(!panel) return false; @@ -277,7 +281,7 @@ bool LLNearbyChatScreenChannel::createPoolToast() return true; } -void LLNearbyChatScreenChannel::addNotification(LLSD& notification) +void LLNearbyChatScreenChannel::addChat(LLSD& chat) { //look in pool. if there is any message if(mStopProcessing) @@ -289,8 +293,8 @@ void LLNearbyChatScreenChannel::addNotification(LLSD& notification) if(m_active_toasts.size()) { - LLUUID fromID = notification["from_id"].asUUID(); // agent id or object id - std::string from = notification["from"].asString(); + LLUUID fromID = chat["from_id"].asUUID(); // agent id or object id + std::string from = chat["from"].asString(); LLToast* toast = m_active_toasts[0].get(); if (toast) { @@ -298,7 +302,7 @@ void LLNearbyChatScreenChannel::addNotification(LLSD& notification) if(panel && panel->messageID() == fromID && panel->getFromName() == from && panel->canAddText()) { - panel->addMessage(notification); + panel->addMessage(chat); toast->reshapeToPanel(); toast->startTimer(); @@ -316,11 +320,11 @@ void LLNearbyChatScreenChannel::addNotification(LLSD& notification) LL_DEBUGS("NearbyChat") << "Empty pool" << llendl; if(!createPoolToast())//created toast will go to pool. so next call will find it return; - addNotification(notification); + addChat(chat); return; } - int chat_type = notification["chat_type"].asInteger(); + int chat_type = chat["chat_type"].asInteger(); if( ((EChatType)chat_type == CHAT_TYPE_DEBUG_MSG)) { @@ -339,10 +343,10 @@ void LLNearbyChatScreenChannel::addNotification(LLSD& notification) m_toast_pool.pop_back(); - LLToastPanelBase* panel = dynamic_cast<LLToastPanelBase*>(toast->getPanel()); + LLNearbyChatToastPanel* panel = dynamic_cast<LLNearbyChatToastPanel*>(toast->getPanel()); if(!panel) return; - panel->init(notification); + panel->init(chat); toast->reshapeToPanel(); toast->startTimer(); @@ -488,23 +492,23 @@ void LLNearbyChatHandler::processChat(const LLChat& chat_msg, LLNearbyChat* nearby_chat = chat_bar->findChild<LLNearbyChat>("nearby_chat"); // Build notification data - LLSD notification; - notification["message"] = chat_msg.mText; - notification["from"] = chat_msg.mFromName; - notification["from_id"] = chat_msg.mFromID; - notification["time"] = chat_msg.mTime; - notification["source"] = (S32)chat_msg.mSourceType; - notification["chat_type"] = (S32)chat_msg.mChatType; - notification["chat_style"] = (S32)chat_msg.mChatStyle; + LLSD chat; + chat["message"] = chat_msg.mText; + chat["from"] = chat_msg.mFromName; + chat["from_id"] = chat_msg.mFromID; + chat["time"] = chat_msg.mTime; + chat["source"] = (S32)chat_msg.mSourceType; + chat["chat_type"] = (S32)chat_msg.mChatType; + chat["chat_style"] = (S32)chat_msg.mChatStyle; // Pass sender info so that it can be rendered properly (STORM-1021). - notification["sender_slurl"] = LLViewerChat::getSenderSLURL(chat_msg, args); + chat["sender_slurl"] = LLViewerChat::getSenderSLURL(chat_msg, args); if (chat_msg.mChatType == CHAT_TYPE_DIRECT && chat_msg.mText.length() > 0 && chat_msg.mText[0] == '@') { // Send event on to LLEventStream and exit - sChatWatcher->post(notification); + sChatWatcher->post(chat); return; } @@ -551,7 +555,7 @@ void LLNearbyChatHandler::processChat(const LLChat& chat_msg, } // Send event on to LLEventStream - sChatWatcher->post(notification); + sChatWatcher->post(chat); if( !chat_bar->isMinimized() @@ -602,16 +606,16 @@ void LLNearbyChatHandler::processChat(const LLChat& chat_msg, // Add a nearby chat toast. LLUUID id; id.generate(); - notification["id"] = id; + chat["id"] = id; std::string r_color_name = "White"; F32 r_color_alpha = 1.0f; LLViewerChat::getChatColor( chat_msg, r_color_name, r_color_alpha); - notification["text_color"] = r_color_name; - notification["color_alpha"] = r_color_alpha; - notification["font_size"] = (S32)LLViewerChat::getChatFontSize() ; - notification["message"] = toast_msg; - channel->addNotification(notification); + chat["text_color"] = r_color_name; + chat["color_alpha"] = r_color_alpha; + chat["font_size"] = (S32)LLViewerChat::getChatFontSize() ; + chat["message"] = toast_msg; + channel->addChat(chat); } } diff --git a/indra/newview/llnotificationgrouphandler.cpp b/indra/newview/llnotificationgrouphandler.cpp index 6946b78cbf..18cd94e685 100644 --- a/indra/newview/llnotificationgrouphandler.cpp +++ b/indra/newview/llnotificationgrouphandler.cpp @@ -44,7 +44,6 @@ LLGroupHandler::LLGroupHandler() LLScreenChannel* channel = LLChannelManager::getInstance()->createNotificationChannel(); if(channel) { - channel->addOnRejectToastCallback(boost::bind(&LLGroupHandler::onRejectToast, this, _1)); mChannel = channel->getHandle(); } } @@ -94,16 +93,6 @@ bool LLGroupHandler::processNotification(const LLNotificationPtr& notification) return false; } -//-------------------------------------------------------------------------- -void LLGroupHandler::onRejectToast(LLUUID& id) -{ - LLNotificationPtr notification = LLNotifications::instance().find(id); - - if (notification && mItems.find(notification) != mItems.end()) - { - LLNotifications::instance().cancel(notification); - } -} //-------------------------------------------------------------------------- diff --git a/indra/newview/llnotificationhandler.h b/indra/newview/llnotificationhandler.h index 83d228e799..4d54bb78fc 100644 --- a/indra/newview/llnotificationhandler.h +++ b/indra/newview/llnotificationhandler.h @@ -95,16 +95,9 @@ public: // base interface functions /*virtual*/ void onAdd(LLNotificationPtr p) { processNotification(p); } /*virtual*/ void onLoad(LLNotificationPtr p) { processNotification(p); } - /*virtual*/ void onDelete(LLNotificationPtr p) { if (mChannel.get()) mChannel.get()->killToastByNotificationID(p->getID());} + /*virtual*/ void onDelete(LLNotificationPtr p) { if (mChannel.get()) mChannel.get()->removeToastByNotificationID(p->getID());} virtual bool processNotification(const LLNotificationPtr& notify)=0; - -protected : - static void init(); - void removeExclusiveNotifications(const LLNotificationPtr& notif); - - typedef std::list< std::set<std::string> > exclusive_notif_sets; - static exclusive_notif_sets sExclusiveNotificationGroups; }; /** @@ -148,7 +141,6 @@ public: /*virtual*/ bool processNotification(const LLNotificationPtr& p); protected: - /*virtual*/ void onRejectToast(const LLUUID& id); /*virtual*/ void initChannel(); }; @@ -169,9 +161,6 @@ public: protected: /*virtual*/ void onDeleteToast(LLToast* toast); /*virtual*/ void initChannel(); - - // own handlers - void onRejectToast(LLUUID& id); }; @@ -190,9 +179,6 @@ public: protected: virtual void initChannel(); - - // own handlers - void onRejectToast(LLUUID& id); }; /** @@ -225,15 +211,12 @@ public: virtual ~LLOfferHandler(); // base interface functions - /*virtual*/ void onChange(LLNotificationPtr p) { processNotification(p); } + /*virtual*/ void onChange(LLNotificationPtr p); /*virtual*/ void onDelete(LLNotificationPtr notification); /*virtual*/ bool processNotification(const LLNotificationPtr& p); protected: /*virtual*/ void initChannel(); - - // own handlers - void onRejectToast(LLUUID& id); }; /** diff --git a/indra/newview/llnotificationhandlerutil.cpp b/indra/newview/llnotificationhandlerutil.cpp index 1494ac6b5c..cba22b233b 100644 --- a/indra/newview/llnotificationhandlerutil.cpp +++ b/indra/newview/llnotificationhandlerutil.cpp @@ -41,75 +41,9 @@ using namespace LLNotificationsUI; -// static -std::list< std::set<std::string> > LLSysHandler::sExclusiveNotificationGroups; - -// static -void LLSysHandler::init() -{ - std::set<std::string> online_offline_group; - online_offline_group.insert("FriendOnline"); - online_offline_group.insert("FriendOffline"); - - sExclusiveNotificationGroups.push_back(online_offline_group); -} - LLSysHandler::LLSysHandler(const std::string& name, const std::string& notification_type) : LLNotificationChannel(name, "Visible", LLNotificationFilters::filterBy<std::string>(&LLNotification::getType, notification_type)) -{ - if(sExclusiveNotificationGroups.empty()) - { - init(); - } -} - -void LLSysHandler::removeExclusiveNotifications(const LLNotificationPtr& notif) -{ - LLScreenChannel* channel = dynamic_cast<LLScreenChannel *>(mChannel.get()); - if (channel == NULL) - { - return; - } - - class ExclusiveMatcher: public LLScreenChannel::Matcher - { - public: - ExclusiveMatcher(const std::set<std::string>& excl_group, - const std::string& from_name) : - mExclGroup(excl_group), mFromName(from_name) - { - } - bool matches(const LLNotificationPtr notification) const - { - for (std::set<std::string>::const_iterator it = mExclGroup.begin(); it - != mExclGroup.end(); it++) - { - std::string from_name = LLHandlerUtil::getSubstitutionName(notification); - if (notification->getName() == *it && from_name == mFromName) - { - return true; - } - } - return false; - } - private: - const std::set<std::string>& mExclGroup; - const std::string& mFromName; - }; - - - for (exclusive_notif_sets::iterator it = sExclusiveNotificationGroups.begin(); it - != sExclusiveNotificationGroups.end(); it++) - { - std::set<std::string> group = *it; - std::set<std::string>::iterator g_it = group.find(notif->getName()); - if (g_it != group.end()) - { - channel->killMatchedToasts(ExclusiveMatcher(group, - LLHandlerUtil::getSubstitutionName(notif))); - } - } -} +{} // static bool LLHandlerUtil::isIMFloaterOpened(const LLNotificationPtr& notification) diff --git a/indra/newview/llnotificationofferhandler.cpp b/indra/newview/llnotificationofferhandler.cpp index 2112b0d35e..6e641575fa 100644 --- a/indra/newview/llnotificationofferhandler.cpp +++ b/indra/newview/llnotificationofferhandler.cpp @@ -48,7 +48,6 @@ LLOfferHandler::LLOfferHandler() if(channel) { channel->setControlHovering(true); - channel->addOnRejectToastCallback(boost::bind(&LLOfferHandler::onRejectToast, this, _1)); mChannel = channel->getHandle(); } } @@ -81,92 +80,95 @@ bool LLOfferHandler::processNotification(const LLNotificationPtr& notification) } - if( notification->getPayload().has("give_inventory_notification") + if( notification->getPayload().has("give_inventory_notification") && notification->getPayload()["give_inventory_notification"].asBoolean() == false) - { - // This is an original inventory offer, so add a script floater - LLScriptFloaterManager::instance().onAddNotification(notification->getID()); - } - else - { + { + // This is an original inventory offer, so add a script floater + LLScriptFloaterManager::instance().onAddNotification(notification->getID()); + } + else + { bool add_notif_to_im = notification->canLogToIM() && notification->hasFormElements(); - notification->setReusable(add_notif_to_im); - - LLUUID session_id; if (add_notif_to_im) - { - const std::string name = LLHandlerUtil::getSubstitutionName(notification); + { + const std::string name = LLHandlerUtil::getSubstitutionName(notification); - LLUUID from_id = notification->getPayload()["from_id"]; + LLUUID from_id = notification->getPayload()["from_id"]; - session_id = LLHandlerUtil::spawnIMSession(name, from_id); - LLHandlerUtil::addNotifPanelToIM(notification); - } + LLHandlerUtil::spawnIMSession(name, from_id); + LLHandlerUtil::addNotifPanelToIM(notification); + } - if (notification->getPayload().has("SUPPRESS_TOAST") - && notification->getPayload()["SUPPRESS_TOAST"]) - { - LLNotificationsUtil::cancel(notification); - } + if (!notification->canShowToast()) + { + LLNotificationsUtil::cancel(notification); + } else if(!notification->canLogToIM() || !LLHandlerUtil::isIMFloaterOpened(notification)) - { - LLToastNotifyPanel* notify_box = new LLToastNotifyPanel(notification); - // don't close notification on panel destroy since it will be used by IM floater - notify_box->setCloseNotificationOnDestroy(!add_notif_to_im); - LLToast::Params p; - p.notif_id = notification->getID(); - p.notification = notification; - p.panel = notify_box; - // we not save offer notifications to the syswell floater that should be added to the IM floater + { + LLToastNotifyPanel* notify_box = new LLToastNotifyPanel(notification); + LLToast::Params p; + p.notif_id = notification->getID(); + p.notification = notification; + p.panel = notify_box; + // we not save offer notifications to the syswell floater that should be added to the IM floater p.can_be_stored = !add_notif_to_im; - LLScreenChannel* channel = dynamic_cast<LLScreenChannel*>(mChannel.get()); - if(channel) - channel->addToast(p); - } + LLScreenChannel* channel = dynamic_cast<LLScreenChannel*>(mChannel.get()); + if(channel) + channel->addToast(p); + } if (notification->canLogToIM()) - { - // log only to file if notif panel can be embedded to IM and IM is opened + { + // log only to file if notif panel can be embedded to IM and IM is opened bool file_only = add_notif_to_im && LLHandlerUtil::isIMFloaterOpened(notification); LLHandlerUtil::logToIMP2P(notification, file_only); - } - } + } + } return false; - } +} -/*virtual*/ void LLOfferHandler::onDelete(LLNotificationPtr notification) +/*virtual*/ void LLOfferHandler::onChange(LLNotificationPtr p) +{ + LLToastNotifyPanel* panelp = LLToastNotifyPanel::getInstance(p->getID()); + if (panelp) { - if( notification->getPayload().has("give_inventory_notification") - && !notification->getPayload()["give_inventory_notification"] ) + // + // HACK: if we're dealing with a notification embedded in IM, update it + // otherwise remove its toast + // + if (dynamic_cast<LLIMToastNotifyPanel*>(panelp)) { - // Remove original inventory offer script floater - LLScriptFloaterManager::instance().onRemoveNotification(notification->getID()); + panelp->updateNotification(); } else { - if (notification->canLogToIM() - && notification->hasFormElements() - && !LLHandlerUtil::isIMFloaterOpened(notification)) - { - LLHandlerUtil::decIMMesageCounter(notification); - } - mChannel.get()->killToastByNotificationID(notification->getID()); + // if notification has changed, hide it + mChannel.get()->removeToastByNotificationID(p->getID()); } } +} -//-------------------------------------------------------------------------- -void LLOfferHandler::onRejectToast(LLUUID& id) -{ - LLNotificationPtr notification = LLNotifications::instance().find(id); - if (notification - && mItems.find(notification) != mItems.end() - // don't delete notification since it may be used by IM floater - && (!notification->canLogToIM() || !notification->hasFormElements())) +/*virtual*/ void LLOfferHandler::onDelete(LLNotificationPtr notification) +{ + if( notification->getPayload().has("give_inventory_notification") + && !notification->getPayload()["give_inventory_notification"] ) + { + // Remove original inventory offer script floater + LLScriptFloaterManager::instance().onRemoveNotification(notification->getID()); + } + else { - LLNotifications::instance().cancel(notification); + if (notification->canLogToIM() + && notification->hasFormElements() + && !LLHandlerUtil::isIMFloaterOpened(notification)) + { + LLHandlerUtil::decIMMesageCounter(notification); + } + mChannel.get()->removeToastByNotificationID(notification->getID()); } } + diff --git a/indra/newview/llnotificationscripthandler.cpp b/indra/newview/llnotificationscripthandler.cpp index 8472f9b2ae..9f7d0cc2f5 100644 --- a/indra/newview/llnotificationscripthandler.cpp +++ b/indra/newview/llnotificationscripthandler.cpp @@ -46,7 +46,6 @@ LLScriptHandler::LLScriptHandler() if(channel) { channel->setControlHovering(true); - channel->addOnRejectToastCallback(boost::bind(&LLScriptHandler::onRejectToast, this, _1)); mChannel = channel->getHandle(); } } @@ -116,7 +115,7 @@ void LLScriptHandler::onDelete( LLNotificationPtr notification ) } else { - mChannel.get()->killToastByNotificationID(notification->getID()); + mChannel.get()->removeToastByNotificationID(notification->getID()); } } @@ -135,19 +134,6 @@ void LLScriptHandler::onDeleteToast(LLToast* toast) } } -//-------------------------------------------------------------------------- -void LLScriptHandler::onRejectToast(LLUUID& id) -{ - LLNotificationPtr notification = LLNotifications::instance().find(id); - - if (notification && mItems.find(notification) != mItems.end()) - { - LLNotifications::instance().cancel(notification); - } -} - -//-------------------------------------------------------------------------- - diff --git a/indra/newview/llnotificationtiphandler.cpp b/indra/newview/llnotificationtiphandler.cpp index 3588721849..a1d5db2e27 100644 --- a/indra/newview/llnotificationtiphandler.cpp +++ b/indra/newview/llnotificationtiphandler.cpp @@ -48,7 +48,6 @@ LLTipHandler::LLTipHandler() LLScreenChannel* channel = LLChannelManager::getInstance()->createNotificationChannel(); if(channel) { - channel->addOnRejectToastCallback(boost::bind(&LLTipHandler::onRejectToast, this, _1)); mChannel = channel->getHandle(); } } @@ -127,22 +126,8 @@ bool LLTipHandler::processNotification(const LLNotificationPtr& notification) p.is_tip = true; p.can_be_stored = false; - removeExclusiveNotifications(notification); - LLScreenChannel* channel = dynamic_cast<LLScreenChannel*>(mChannel.get()); if(channel) channel->addToast(p); return false; } - -//-------------------------------------------------------------------------- - -void LLTipHandler::onRejectToast(const LLUUID& id) -{ - LLNotificationPtr notification = LLNotifications::instance().find(id); - - if (notification && mItems.find(notification) != mItems.end()) - { - LLNotifications::instance().cancel(notification); - } -} diff --git a/indra/newview/llscreenchannel.cpp b/indra/newview/llscreenchannel.cpp index 003b53b28c..839ca0f9c5 100644 --- a/indra/newview/llscreenchannel.cpp +++ b/indra/newview/llscreenchannel.cpp @@ -265,7 +265,14 @@ void LLScreenChannel::addToast(const LLToast::Params& p) if(!show_toast && !store_toast) { - mRejectToastSignal(p.notif_id); + LLNotificationPtr notification = LLNotifications::instance().find(p.notif_id); + + if (notification && + (!notification->canLogToIM() || !notification->hasFormElements())) + { + // only cancel notification if it isn't being used in IM session + LLNotifications::instance().cancel(notification); + } return; } @@ -432,34 +439,12 @@ void LLScreenChannel::loadStoredToastByNotificationIDToChannel(LLUUID id) } //-------------------------------------------------------------------------- -void LLScreenChannel::removeStoredToastByNotificationID(LLUUID id) -{ - // *TODO: may be remove this function - std::vector<ToastElem>::iterator it = find(mStoredToastList.begin(), mStoredToastList.end(), id); - - if( it == mStoredToastList.end() ) - return; - - const LLToast* toast = it->getToast(); - if (toast) - { - mRejectToastSignal(toast->getNotificationID()); - } - - // Call find() once more, because the mStoredToastList could have been changed - // in mRejectToastSignal callback and the iterator could have become invalid. - it = find(mStoredToastList.begin(), mStoredToastList.end(), id); - if (it != mStoredToastList.end()) - { - mStoredToastList.erase(it); - } -} - -//-------------------------------------------------------------------------- void LLScreenChannel::killToastByNotificationID(LLUUID id) { // searching among toasts on a screen std::vector<ToastElem>::iterator it = find(mToastList.begin(), mToastList.end(), id); + LLNotificationPtr notification = LLNotifications::instance().find(id); + if (!notification) return; if( it != mToastList.end()) { @@ -472,42 +457,67 @@ void LLScreenChannel::killToastByNotificationID(LLUUID id) // the toast will be destroyed. if(toast && toast->isNotificationValid()) { - mRejectToastSignal(toast->getNotificationID()); + if (!notification->canLogToIM() || !notification->hasFormElements()) + { + // only cancel notification if it isn't being used in IM session + LLNotifications::instance().cancel(notification); + } } else { - - deleteToast(toast); - mToastList.erase(it); - redrawToasts(); + removeToastByNotificationID(id); } - return; } - - // searching among stored toasts - it = find(mStoredToastList.begin(), mStoredToastList.end(), id); - - if( it != mStoredToastList.end() ) + else { - LLToast* toast = it->getToast(); - if (toast) + // searching among stored toasts + it = find(mStoredToastList.begin(), mStoredToastList.end(), id); + + if( it != mStoredToastList.end() ) + { + LLToast* toast = it->getToast(); + if (toast) + { + if (!notification->canLogToIM() || !notification->hasFormElements()) + { + // only cancel notification if it isn't being used in IM session + LLNotifications::instance().cancel(notification); + } + deleteToast(toast); + } + } + + // Call find() once more, because the mStoredToastList could have been changed + // via notification cancellation and the iterator could have become invalid. + it = find(mStoredToastList.begin(), mStoredToastList.end(), id); + if (it != mStoredToastList.end()) { - // send signal to a listener to let him perform some action on toast rejecting - mRejectToastSignal(toast->getNotificationID()); - deleteToast(toast); + mStoredToastList.erase(it); + } } } - // Call find() once more, because the mStoredToastList could have been changed - // in mRejectToastSignal callback and the iterator could have become invalid. - it = find(mStoredToastList.begin(), mStoredToastList.end(), id); - if (it != mStoredToastList.end()) +void LLScreenChannel::removeToastByNotificationID(LLUUID id) +{ + std::vector<ToastElem>::iterator it = find(mToastList.begin(), mToastList.end(), id); + if( it != mToastList.end()) { - mStoredToastList.erase(it); + deleteToast(it->getToast()); + mToastList.erase(it); + redrawToasts(); + } + else + { + it = find(mStoredToastList.begin(), mStoredToastList.end(), id); + if (it != mStoredToastList.end()) + { + deleteToast(it->getToast()); + mStoredToastList.erase(it); + } } - } + void LLScreenChannel::killMatchedToasts(const Matcher& matcher) { std::list<const LLToast*> to_delete = findToasts(matcher); diff --git a/indra/newview/llscreenchannel.h b/indra/newview/llscreenchannel.h index eaff61a0f4..e5f4807ab7 100644 --- a/indra/newview/llscreenchannel.h +++ b/indra/newview/llscreenchannel.h @@ -84,6 +84,7 @@ public: // kill or modify a toast by its ID virtual void killToastByNotificationID(LLUUID id) {}; virtual void modifyToastNotificationByID(LLUUID id, LLSD data) {}; + virtual void removeToastByNotificationID(LLUUID id){}; // hide all toasts from screen, but not remove them from a channel virtual void hideToastsFromScreen() {}; @@ -175,6 +176,7 @@ public: void addToast(const LLToast::Params& p); // kill or modify a toast by its ID void killToastByNotificationID(LLUUID id); + void removeToastByNotificationID(LLUUID id); void killMatchedToasts(const Matcher& matcher); void modifyToastByNotificationID(LLUUID id, LLPanel* panel); // hide all toasts from screen, but not remove them from a channel @@ -195,8 +197,6 @@ public: void loadStoredToastsToChannel(); // finds a toast among stored by its Notification ID and throws it on a screen to a channel void loadStoredToastByNotificationIDToChannel(LLUUID id); - // removes a toast from stored finding it by its Notification ID - void removeStoredToastByNotificationID(LLUUID id); // removes from channel all toasts that belongs to the certain IM session void removeToastsBySessionID(LLUUID id); // remove all storable toasts from screen and store them @@ -229,13 +229,9 @@ public: // signal on storing of faded toasts event typedef boost::signals2::signal<void (LLPanel* info_panel, const LLUUID id)> store_toast_signal_t; boost::signals2::connection addOnStoreToastCallback(store_toast_signal_t::slot_type cb) { return mOnStoreToast.connect(cb); } - // signal on rejecting of a toast event - typedef boost::signals2::signal<void (LLUUID id)> reject_toast_signal_t; - boost::signals2::connection addOnRejectToastCallback(reject_toast_signal_t::slot_type cb) { return mRejectToastSignal.connect(cb); } private: store_toast_signal_t mOnStoreToast; - reject_toast_signal_t mRejectToastSignal; class ToastElem { diff --git a/indra/newview/lltoast.h b/indra/newview/lltoast.h index e1d99b1bcb..ea62f758f8 100644 --- a/indra/newview/lltoast.h +++ b/indra/newview/lltoast.h @@ -169,6 +169,7 @@ public: // get/set Toast's flags or states // get information whether the notification corresponding to the toast is valid or not bool isNotificationValid(); + // get toast's Notification ID const LLUUID getNotificationID() const { return mNotificationID;} // get toast's Session ID @@ -212,7 +213,7 @@ private: //LLRootHandle<LLToast> mHandle; - LLPanel* mWrapperPanel; + LLPanel* mWrapperPanel; // timer counts a lifetime of a toast std::auto_ptr<LLToastLifeTimer> mTimer; @@ -220,8 +221,8 @@ private: F32 mToastLifetime; // in seconds F32 mToastFadingTime; // in seconds - LLPanel* mPanel; - LLButton* mHideBtn; + LLPanel* mPanel; + LLButton* mHideBtn; LLColor4 mBgColor; bool mCanFade; diff --git a/indra/newview/lltoastimpanel.h b/indra/newview/lltoastimpanel.h index a803387576..279dd69bc7 100644 --- a/indra/newview/lltoastimpanel.h +++ b/indra/newview/lltoastimpanel.h @@ -41,11 +41,11 @@ public: struct Params { LLNotificationPtr notification; - LLUUID avatar_id; - LLUUID session_id; - std::string from; - std::string time; - std::string message; + LLUUID avatar_id, + session_id; + std::string from, + time, + message; Params() {} }; diff --git a/indra/newview/lltoastnotifypanel.cpp b/indra/newview/lltoastnotifypanel.cpp index dc5cc88dc4..77a5a5d17d 100644 --- a/indra/newview/lltoastnotifypanel.cpp +++ b/indra/newview/lltoastnotifypanel.cpp @@ -45,6 +45,9 @@ const S32 BOTTOM_PAD = VPAD * 3; const S32 IGNORE_BTN_TOP_DELTA = 3*VPAD;//additional ignore_btn padding S32 BUTTON_WIDTH = 90; +// *TODO: magic numbers(???) - copied from llnotify.cpp(250) +const S32 MAX_LENGTH = 512 + 20 + DB_FIRST_NAME_BUF_SIZE + DB_LAST_NAME_BUF_SIZE + DB_INV_ITEM_NAME_BUF_SIZE; + //static const LLFontGL* LLToastNotifyPanel::sFont = NULL; @@ -52,171 +55,24 @@ const LLFontGL* LLToastNotifyPanel::sFontSmall = NULL; LLToastNotifyPanel::button_click_signal_t LLToastNotifyPanel::sButtonClickSignal; -LLToastNotifyPanel::LLToastNotifyPanel(const LLNotificationPtr& notification, const LLRect& rect, bool show_images) : -LLToastPanel(notification), -mTextBox(NULL), -mInfoPanel(NULL), -mControlPanel(NULL), -mNumOptions(0), -mNumButtons(0), -mAddedDefaultBtn(false), -mCloseNotificationOnDestroy(true) +LLToastNotifyPanel::LLToastNotifyPanel(const LLNotificationPtr& notification, const LLRect& rect, bool show_images) +: LLToastPanel(notification), + LLInstanceTracker(notification->getID()) { - buildFromFile( "panel_notification.xml"); - if(rect != LLRect::null) - { - this->setShape(rect); - } - mInfoPanel = getChild<LLPanel>("info_panel"); - mControlPanel = getChild<LLPanel>("control_panel"); - BUTTON_WIDTH = gSavedSettings.getS32("ToastButtonWidth"); - // customize panel's attributes - // is it intended for displaying a tip? - mIsTip = notification->getType() == "notifytip"; - // is it a script dialog? - mIsScriptDialog = (notification->getName() == "ScriptDialog" || notification->getName() == "ScriptDialogGroup"); - // is it a caution? - // - // caution flag can be set explicitly by specifying it in the notification payload, or it can be set implicitly if the - // notify xml template specifies that it is a caution - // tip-style notification handle 'caution' differently -they display the tip in a different color - mIsCaution = notification->getPriority() >= NOTIFICATION_PRIORITY_HIGH; + init(rect, show_images); - // setup parameters - // get a notification message - mMessage = notification->getMessage(); - // init font variables - if (!sFont) - { - sFont = LLFontGL::getFontSansSerif(); - sFontSmall = LLFontGL::getFontSansSerifSmall(); - } - // initialize - setFocusRoot(!mIsTip); - // get a form for the notification - LLNotificationFormPtr form(notification->getForm()); - // get number of elements - mNumOptions = form->getNumElements(); - // customize panel's outfit - // preliminary adjust panel's layout - //move to the end - //mIsTip ? adjustPanelForTipNotice() : adjustPanelForScriptNotice(form); - - // adjust text options according to the notification type - // add a caution textbox at the top of a caution notification - if (mIsCaution && !mIsTip) - { - mTextBox = getChild<LLTextBox>("caution_text_box"); - } - else - { - mTextBox = getChild<LLTextEditor>("text_editor_box"); - } - - // *TODO: magic numbers(???) - copied from llnotify.cpp(250) - const S32 MAX_LENGTH = 512 + 20 + DB_FIRST_NAME_BUF_SIZE + DB_LAST_NAME_BUF_SIZE + DB_INV_ITEM_NAME_BUF_SIZE; - - mTextBox->setMaxTextLength(MAX_LENGTH); - mTextBox->setVisible(TRUE); - mTextBox->setPlainText(!show_images); - mTextBox->setValue(notification->getMessage()); - - // add buttons for a script notification - if (mIsTip) - { - adjustPanelForTipNotice(); - } - else - { - std::vector<index_button_pair_t> buttons; - buttons.reserve(mNumOptions); - S32 buttons_width = 0; - // create all buttons and accumulate they total width to reshape mControlPanel - for (S32 i = 0; i < mNumOptions; i++) - { - LLSD form_element = form->getElement(i); - if (form_element["type"].asString() != "button") - { - // not a button. - continue; - } - if (form_element["name"].asString() == TEXTBOX_MAGIC_TOKEN) - { - // a textbox pretending to be a button. - continue; - } - LLButton* new_button = createButton(form_element, TRUE); - buttons_width += new_button->getRect().getWidth(); - S32 index = form_element["index"].asInteger(); - buttons.push_back(index_button_pair_t(index,new_button)); - } - if (buttons.empty()) - { - addDefaultButton(); - } - else - { - const S32 button_panel_width = mControlPanel->getRect().getWidth();// do not change width of the panel - S32 button_panel_height = mControlPanel->getRect().getHeight(); - //try get an average h_pad to spread out buttons - S32 h_pad = (button_panel_width - buttons_width) / (S32(buttons.size())); - if(h_pad < 2*HPAD) - { - /* - * Probably it is a scriptdialog toast - * for a scriptdialog toast h_pad can be < 2*HPAD if we have a lot of buttons. - * In last case set default h_pad to avoid heaping of buttons - */ - S32 button_per_row = button_panel_width / BUTTON_WIDTH; - h_pad = (button_panel_width % BUTTON_WIDTH) / (button_per_row - 1);// -1 because we do not need space after last button in a row - if(h_pad < 2*HPAD) // still not enough space between buttons ? - { - h_pad = 2*HPAD; - } - } - if (mIsScriptDialog) - { - // we are using default width for script buttons so we can determinate button_rows - //to get a number of rows we divide the required width of the buttons to button_panel_width - S32 button_rows = llceil(F32(buttons.size() - 1) * (BUTTON_WIDTH + h_pad) / button_panel_width); - //S32 button_rows = (buttons.size() - 1) * (BUTTON_WIDTH + h_pad) / button_panel_width; - //reserve one row for the ignore_btn - button_rows++; - //calculate required panel height for scripdialog notification. - button_panel_height = button_rows * (BTN_HEIGHT + VPAD) + IGNORE_BTN_TOP_DELTA + BOTTOM_PAD; - } - else - { - // in common case buttons can have different widths so we need to calculate button_rows according to buttons_width - //S32 button_rows = llceil(F32(buttons.size()) * (buttons_width + h_pad) / button_panel_width); - S32 button_rows = llceil(F32((buttons.size() - 1) * h_pad + buttons_width) / button_panel_width); - //calculate required panel height - button_panel_height = button_rows * (BTN_HEIGHT + VPAD) + BOTTOM_PAD; - } - - // we need to keep min width and max height to make visible all buttons, because width of the toast can not be changed - adjustPanelForScriptNotice(button_panel_width, button_panel_height); - updateButtonsLayout(buttons, h_pad); - // save buttons for later use in disableButtons() - mButtons.assign(buttons.begin(), buttons.end()); - } - } - // adjust panel's height to the text size - mInfoPanel->setFollowsAll(); - snapToMessageHeight(mTextBox, MAX_LENGTH); - - if(notification->isReusable()) - { - mButtonClickConnection = sButtonClickSignal.connect( - boost::bind(&LLToastNotifyPanel::onToastPanelButtonClicked, this, _1, _2)); - - if(notification->isRespondedTo()) - { - // User selected an option in toast, now disable required buttons in IM window - disableRespondedOptions(notification); - } - } + //if(notification->isRespondedTo()) + //{ + // // User selected an option in toast, now disable required buttons in IM window + // disableRespondedOptions(notification); + //} + // + //if(notification->isReusable()) + //{ + // mButtonClickConnection = sButtonClickSignal.connect( + // boost::bind(&LLToastNotifyPanel::disableRespondedOptions, this, notification)); + //} } void LLToastNotifyPanel::addDefaultButton() { @@ -235,7 +91,6 @@ void LLToastNotifyPanel::addDefaultButton() } LLButton* LLToastNotifyPanel::createButton(const LLSD& form_element, BOOL is_option) { - InstanceAndS32* userdata = new InstanceAndS32; userdata->mSelf = this; userdata->mButtonName = is_option ? form_element["name"].asString() : ""; @@ -245,14 +100,15 @@ LLButton* LLToastNotifyPanel::createButton(const LLSD& form_element, BOOL is_opt LLButton::Params p; bool is_ignore_btn = form_element["index"].asInteger() == -1; const LLFontGL* font = is_ignore_btn ? sFontSmall: sFont; // for ignore button in script dialog - p.name(form_element["name"].asString()); - p.label(form_element["text"].asString()); - p.font(font); + p.name = form_element["name"].asString(); + p.label = form_element["text"].asString(); + p.font = font; p.rect.height = BTN_HEIGHT; p.click_callback.function(boost::bind(&LLToastNotifyPanel::onClickButton, userdata)); p.rect.width = BUTTON_WIDTH; p.auto_resize = false; p.follows.flags(FOLLOWS_LEFT | FOLLOWS_BOTTOM); + p.enabled = !form_element.has("enabled") || form_element["enabled"].asBoolean(); if (mIsCaution) { p.image_color(LLUIColorTable::instance().getColor("ButtonCautionImageColor")); @@ -287,14 +143,9 @@ LLToastNotifyPanel::~LLToastNotifyPanel() mButtonClickConnection.disconnect(); std::for_each(mBtnCallbackData.begin(), mBtnCallbackData.end(), DeletePointer()); - if (mCloseNotificationOnDestroy && LLNotificationsUtil::find(mNotification->getID()) != NULL) + if (mIsTip) { - // let reusable notification be deleted - mNotification->setReusable(false); - if (!mNotification->isPersistent()) - { - LLNotifications::getInstance()->cancel(mNotification); - } + LLNotifications::getInstance()->cancel(mNotification); } } @@ -393,103 +244,103 @@ void LLToastNotifyPanel::adjustPanelForTipNotice() } } -typedef std::set<std::string> button_name_set_t; -typedef std::map<std::string, button_name_set_t> disable_button_map_t; - -disable_button_map_t initUserGiveItemDisableButtonMap() -{ - // see EXT-5905 for disable rules - - disable_button_map_t disable_map; - button_name_set_t buttons; - - buttons.insert("Show"); - disable_map.insert(std::make_pair("Show", buttons)); - - buttons.insert("Discard"); - disable_map.insert(std::make_pair("Discard", buttons)); - - buttons.insert("Mute"); - disable_map.insert(std::make_pair("Mute", buttons)); - - return disable_map; -} - -disable_button_map_t initTeleportOfferedDisableButtonMap() -{ - disable_button_map_t disable_map; - button_name_set_t buttons; - - buttons.insert("Teleport"); - buttons.insert("Cancel"); - - disable_map.insert(std::make_pair("Teleport", buttons)); - disable_map.insert(std::make_pair("Cancel", buttons)); - - return disable_map; -} - -disable_button_map_t initFriendshipOfferedDisableButtonMap() -{ - disable_button_map_t disable_map; - button_name_set_t buttons; - - buttons.insert("Accept"); - buttons.insert("Decline"); - - disable_map.insert(std::make_pair("Accept", buttons)); - disable_map.insert(std::make_pair("Decline", buttons)); - - return disable_map; -} - -button_name_set_t getButtonDisableList(const std::string& notification_name, const std::string& button_name) -{ - static disable_button_map_t user_give_item_disable_map = initUserGiveItemDisableButtonMap(); - static disable_button_map_t teleport_offered_disable_map = initTeleportOfferedDisableButtonMap(); - static disable_button_map_t friendship_offered_disable_map = initFriendshipOfferedDisableButtonMap(); - - disable_button_map_t::const_iterator it; - disable_button_map_t::const_iterator it_end; - disable_button_map_t search_map; - - if("UserGiveItem" == notification_name) - { - search_map = user_give_item_disable_map; - } - else if("TeleportOffered" == notification_name) - { - search_map = teleport_offered_disable_map; - } - else if("OfferFriendship" == notification_name) - { - search_map = friendship_offered_disable_map; - } - - it = search_map.find(button_name); - it_end = search_map.end(); - - if(it_end != it) - { - return it->second; - } - return button_name_set_t(); -} - -void LLToastNotifyPanel::disableButtons(const std::string& notification_name, const std::string& selected_button) -{ - button_name_set_t buttons = getButtonDisableList(notification_name, selected_button); - - std::vector<index_button_pair_t>::const_iterator it = mButtons.begin(); - for ( ; it != mButtons.end(); it++) - { - LLButton* btn = it->second; - if(buttons.find(btn->getName()) != buttons.end()) - { - btn->setEnabled(FALSE); - } - } -} +//typedef std::set<std::string> button_name_set_t; +//typedef std::map<std::string, button_name_set_t> disable_button_map_t; +// +//disable_button_map_t initUserGiveItemDisableButtonMap() +//{ +// // see EXT-5905 for disable rules +// +// disable_button_map_t disable_map; +// button_name_set_t buttons; +// +// buttons.insert("Show"); +// disable_map.insert(std::make_pair("Show", buttons)); +// +// buttons.insert("Discard"); +// disable_map.insert(std::make_pair("Discard", buttons)); +// +// buttons.insert("Mute"); +// disable_map.insert(std::make_pair("Mute", buttons)); +// +// return disable_map; +//} +// +//disable_button_map_t initTeleportOfferedDisableButtonMap() +//{ +// disable_button_map_t disable_map; +// button_name_set_t buttons; +// +// buttons.insert("Teleport"); +// buttons.insert("Cancel"); +// +// disable_map.insert(std::make_pair("Teleport", buttons)); +// disable_map.insert(std::make_pair("Cancel", buttons)); +// +// return disable_map; +//} +// +//disable_button_map_t initFriendshipOfferedDisableButtonMap() +//{ +// disable_button_map_t disable_map; +// button_name_set_t buttons; +// +// buttons.insert("Accept"); +// buttons.insert("Decline"); +// +// disable_map.insert(std::make_pair("Accept", buttons)); +// disable_map.insert(std::make_pair("Decline", buttons)); +// +// return disable_map; +//} +// +//button_name_set_t getButtonDisableList(const std::string& notification_name, const std::string& button_name) +//{ +// static disable_button_map_t user_give_item_disable_map = initUserGiveItemDisableButtonMap(); +// static disable_button_map_t teleport_offered_disable_map = initTeleportOfferedDisableButtonMap(); +// static disable_button_map_t friendship_offered_disable_map = initFriendshipOfferedDisableButtonMap(); +// +// disable_button_map_t::const_iterator it; +// disable_button_map_t::const_iterator it_end; +// disable_button_map_t search_map; +// +// if("UserGiveItem" == notification_name) +// { +// search_map = user_give_item_disable_map; +// } +// else if("TeleportOffered" == notification_name) +// { +// search_map = teleport_offered_disable_map; +// } +// else if("OfferFriendship" == notification_name) +// { +// search_map = friendship_offered_disable_map; +// } +// +// it = search_map.find(button_name); +// it_end = search_map.end(); +// +// if(it_end != it) +// { +// return it->second; +// } +// return button_name_set_t(); +//} + +//void LLToastNotifyPanel::disableButtons(const std::string& notification_name, const std::string& selected_button) +//{ + //button_name_set_t buttons = getButtonDisableList(notification_name, selected_button); + + //std::vector<index_button_pair_t>::const_iterator it = mButtons.begin(); + //for ( ; it != mButtons.end(); it++) + //{ + // LLButton* btn = it->second; + // if(buttons.find(btn->getName()) != buttons.end()) + // { + // btn->setEnabled(FALSE); + // } + //} +//} // static void LLToastNotifyPanel::onClickButton(void* data) @@ -515,88 +366,263 @@ void LLToastNotifyPanel::onClickButton(void* data) self->mNotification->setResponder(new_info); } + // disable all buttons + self->mControlPanel->setEnabled(FALSE); + + // this might repost notification with new form data/enabled buttons self->mNotification->respond(response); +} - if(is_reusable) +void LLToastNotifyPanel::init( LLRect rect, bool show_images ) +{ + deleteAllChildren(); + + mTextBox = NULL; + mInfoPanel = NULL; + mControlPanel = NULL; + mNumOptions = 0; + mNumButtons = 0; + mAddedDefaultBtn = false; + + buildFromFile( "panel_notification.xml"); + if(rect != LLRect::null) { - sButtonClickSignal(self->mNotification->getID(), button_name); + this->setShape(rect); + } + mInfoPanel = getChild<LLPanel>("info_panel"); + mInfoPanel->setFollowsAll(); + + mControlPanel = getChild<LLPanel>("control_panel"); + BUTTON_WIDTH = gSavedSettings.getS32("ToastButtonWidth"); + // customize panel's attributes + // is it intended for displaying a tip? + mIsTip = mNotification->getType() == "notifytip"; + // is it a script dialog? + mIsScriptDialog = (mNotification->getName() == "ScriptDialog" || mNotification->getName() == "ScriptDialogGroup"); + // is it a caution? + // + // caution flag can be set explicitly by specifying it in the notification payload, or it can be set implicitly if the + // notify xml template specifies that it is a caution + // tip-style notification handle 'caution' differently -they display the tip in a different color + mIsCaution = mNotification->getPriority() >= NOTIFICATION_PRIORITY_HIGH; + + // setup parameters + // get a notification message + mMessage = mNotification->getMessage(); + // init font variables + if (!sFont) + { + sFont = LLFontGL::getFontSansSerif(); + sFontSmall = LLFontGL::getFontSansSerifSmall(); + } + // initialize + setFocusRoot(!mIsTip); + // get a form for the notification + LLNotificationFormPtr form(mNotification->getForm()); + // get number of elements + mNumOptions = form->getNumElements(); + + // customize panel's outfit + // preliminary adjust panel's layout + //move to the end + //mIsTip ? adjustPanelForTipNotice() : adjustPanelForScriptNotice(form); + + // adjust text options according to the notification type + // add a caution textbox at the top of a caution notification + if (mIsCaution && !mIsTip) + { + mTextBox = getChild<LLTextBox>("caution_text_box"); } else { - // disable all buttons - self->mControlPanel->setEnabled(FALSE); + mTextBox = getChild<LLTextEditor>("text_editor_box"); } -} -void LLToastNotifyPanel::onToastPanelButtonClicked(const LLUUID& notification_id, const std::string btn_name) -{ - if(mNotification->getID() == notification_id) + mTextBox->setMaxTextLength(MAX_LENGTH); + mTextBox->setVisible(TRUE); + mTextBox->setPlainText(!show_images); + mTextBox->setValue(mNotification->getMessage()); + + // add buttons for a script notification + if (mIsTip) { - disableButtons(mNotification->getName(), btn_name); + adjustPanelForTipNotice(); } -} - -void LLToastNotifyPanel::disableRespondedOptions(const LLNotificationPtr& notification) -{ - LLSD response = notification->getResponse(); - for (LLSD::map_const_iterator response_it = response.beginMap(); - response_it != response.endMap(); ++response_it) + else { - if (response_it->second.isBoolean() && response_it->second.asBoolean()) + std::vector<index_button_pair_t> buttons; + buttons.reserve(mNumOptions); + S32 buttons_width = 0; + // create all buttons and accumulate they total width to reshape mControlPanel + for (S32 i = 0; i < mNumOptions; i++) { - // that after multiple responses there can be many pressed buttons - // need to process them all - disableButtons(notification->getName(), response_it->first); + LLSD form_element = form->getElement(i); + if (form_element["type"].asString() != "button") + { + // not a button. + continue; + } + if (form_element["name"].asString() == TEXTBOX_MAGIC_TOKEN) + { + // a textbox pretending to be a button. + continue; + } + LLButton* new_button = createButton(form_element, TRUE); + buttons_width += new_button->getRect().getWidth(); + S32 index = form_element["index"].asInteger(); + buttons.push_back(index_button_pair_t(index,new_button)); + } + if (buttons.empty()) + { + addDefaultButton(); + } + else + { + const S32 button_panel_width = mControlPanel->getRect().getWidth();// do not change width of the panel + S32 button_panel_height = mControlPanel->getRect().getHeight(); + //try get an average h_pad to spread out buttons + S32 h_pad = (button_panel_width - buttons_width) / (S32(buttons.size())); + if(h_pad < 2*HPAD) + { + /* + * Probably it is a scriptdialog toast + * for a scriptdialog toast h_pad can be < 2*HPAD if we have a lot of buttons. + * In last case set default h_pad to avoid heaping of buttons + */ + S32 button_per_row = button_panel_width / BUTTON_WIDTH; + h_pad = (button_panel_width % BUTTON_WIDTH) / (button_per_row - 1);// -1 because we do not need space after last button in a row + if(h_pad < 2*HPAD) // still not enough space between buttons ? + { + h_pad = 2*HPAD; + } + } + if (mIsScriptDialog) + { + // we are using default width for script buttons so we can determinate button_rows + //to get a number of rows we divide the required width of the buttons to button_panel_width + S32 button_rows = llceil(F32(buttons.size() - 1) * (BUTTON_WIDTH + h_pad) / button_panel_width); + //S32 button_rows = (buttons.size() - 1) * (BUTTON_WIDTH + h_pad) / button_panel_width; + //reserve one row for the ignore_btn + button_rows++; + //calculate required panel height for scripdialog notification. + button_panel_height = button_rows * (BTN_HEIGHT + VPAD) + IGNORE_BTN_TOP_DELTA + BOTTOM_PAD; + } + else + { + // in common case buttons can have different widths so we need to calculate button_rows according to buttons_width + //S32 button_rows = llceil(F32(buttons.size()) * (buttons_width + h_pad) / button_panel_width); + S32 button_rows = llceil(F32((buttons.size() - 1) * h_pad + buttons_width) / button_panel_width); + //calculate required panel height + button_panel_height = button_rows * (BTN_HEIGHT + VPAD) + BOTTOM_PAD; + } + + // we need to keep min width and max height to make visible all buttons, because width of the toast can not be changed + adjustPanelForScriptNotice(button_panel_width, button_panel_height); + updateButtonsLayout(buttons, h_pad); + // save buttons for later use in disableButtons() + //mButtons.assign(buttons.begin(), buttons.end()); } } + // adjust panel's height to the text size + snapToMessageHeight(mTextBox, MAX_LENGTH); } + +//void LLToastNotifyPanel::onToastPanelButtonClicked(const LLUUID& notification_id, const std::string btn_name) +//{ +// if(mNotification->getID() == notification_id) +// { +// disableButtons(mNotification->getName(), btn_name); +// } +//} + +//void LLToastNotifyPanel::disableRespondedOptions(const LLNotificationPtr& notification) +//{ +// LLSD response = notification->getResponse(); +// for (LLSD::map_const_iterator response_it = response.beginMap(); +// response_it != response.endMap(); ++response_it) +// { +// if (response_it->second.isBoolean() && response_it->second.asBoolean()) +// { +// // that after multiple responses there can be many pressed buttons +// // need to process them all +// disableButtons(notification->getName(), response_it->first); +// } +// } +//} + + ////////////////////////////////////////////////////////////////////////// LLIMToastNotifyPanel::LLIMToastNotifyPanel(LLNotificationPtr& pNotification, const LLUUID& session_id, const LLRect& rect /* = LLRect::null */, - bool show_images /* = true */) - : mSessionID(session_id), LLToastNotifyPanel(pNotification, rect, show_images) + bool show_images /* = true */, LLTextBase* parent_text) +: mSessionID(session_id), LLToastNotifyPanel(pNotification, rect, show_images), + mParentText(parent_text) { - mTextBox->setFollowsAll(); + compactButtons(); } LLIMToastNotifyPanel::~LLIMToastNotifyPanel() { - // We shouldn't delete notification when IM floater exists - // since that notification will be reused by IM floater. - // This may happened when IM floater reloads messages, exactly when user - // changes layout of IM chat log(disable/enable plaintext mode). - // See EXT-6500 - LLIMFloater* im_floater = LLIMFloater::findInstance(mSessionID); - if (im_floater != NULL && !im_floater->isDead()) - { - mCloseNotificationOnDestroy = false; - } } void LLIMToastNotifyPanel::reshape(S32 width, S32 height, BOOL called_from_parent /* = TRUE */) { - S32 text_height = mTextBox->getTextBoundingRect().getHeight(); - S32 widget_height = mTextBox->getRect().getHeight(); - S32 delta = text_height - widget_height; - LLRect rc = getRect(); + LLToastPanel::reshape(width, height, called_from_parent); - rc.setLeftTopAndSize(rc.mLeft, rc.mTop, width, height + delta); - height = rc.getHeight(); - width = rc.getWidth(); + snapToMessageHeight(mTextBox, MAX_LENGTH); +} - bool is_width_changed = width != getRect().getWidth(); +void LLIMToastNotifyPanel::compactButtons() +{ + mTextBox->setFollowsAll(); - LLToastPanel::reshape(width, height, called_from_parent); + //we can't set follows in xml since it broke toasts behavior + setFollows(FOLLOWS_LEFT|FOLLOWS_RIGHT|FOLLOWS_TOP); - // Notification height required to display the text message depends on - // the width of the text box thus if panel width is changed the text box - // width is also changed then reshape() is called to adjust proper height. - if (is_width_changed) + const child_list_t* children = getControlPanel()->getChildList(); + S32 offset = 0; + // Children were added by addChild() which uses push_front to insert them into list, + // so to get buttons in correct order reverse iterator is used (EXT-5906) + for (child_list_t::const_reverse_iterator it = children->rbegin(); it != children->rend(); it++) { - reshape(width, height, called_from_parent); + LLButton * button = dynamic_cast<LLButton*> (*it); + if (button != NULL) + { + button->setOrigin( offset,button->getRect().mBottom); + button->setLeftHPad(2 * HPAD); + button->setRightHPad(2 * HPAD); + // set zero width before perform autoResize() + button->setRect(LLRect(button->getRect().mLeft, + button->getRect().mTop, + button->getRect().mLeft, + button->getRect().mBottom)); + button->setAutoResize(true); + button->autoResize(); + offset += HPAD + button->getRect().getWidth(); + button->setFollowsNone(); + } } + + if (mParentText) + { + mParentText->needsReflow(); + } +} + +void LLIMToastNotifyPanel::updateNotification() +{ + init(LLRect(), true); +} + +void LLIMToastNotifyPanel::init( LLRect rect, bool show_images ) +{ + LLToastNotifyPanel::init(LLRect(), show_images); + + compactButtons(); } + // EOF + diff --git a/indra/newview/lltoastnotifypanel.h b/indra/newview/lltoastnotifypanel.h index db517ec858..f93c7745af 100644 --- a/indra/newview/lltoastnotifypanel.h +++ b/indra/newview/lltoastnotifypanel.h @@ -47,7 +47,7 @@ class LLNotificationForm; * @deprecated this class will be removed after all toast panel types are * implemented in separate classes. */ -class LLToastNotifyPanel: public LLToastPanel +class LLToastNotifyPanel: public LLToastPanel, public LLInstanceTracker<LLToastNotifyPanel, LLUUID> { public: /** @@ -61,10 +61,14 @@ public: * implement right class for desired toast panel. @see LLGenericTipPanel as example. */ LLToastNotifyPanel(const LLNotificationPtr& pNotification, const LLRect& rect = LLRect::null, bool show_images = true); + + virtual void init( LLRect rect, bool show_images ); + virtual ~LLToastNotifyPanel(); LLPanel * getControlPanel() { return mControlPanel; } - void setCloseNotificationOnDestroy(bool close) { mCloseNotificationOnDestroy = close; } + virtual void updateNotification() {} + protected: LLButton* createButton(const LLSD& form_element, BOOL is_option); @@ -76,8 +80,6 @@ protected: }; std::vector<InstanceAndS32*> mBtnCallbackData; - bool mCloseNotificationOnDestroy; - typedef std::pair<int,LLButton*> index_button_pair_t; void adjustPanelForScriptNotice(S32 max_width, S32 max_height); void adjustPanelForTipNotice(); @@ -93,9 +95,9 @@ protected: /** * Disable specific button(s) based on notification name and clicked button */ - void disableButtons(const std::string& notification_name, const std::string& selected_button); + //void disableButtons(const std::string& notification_name, const std::string& selected_button); - std::vector<index_button_pair_t> mButtons; + //std::vector<index_button_pair_t> mButtons; // panel elements LLTextBase* mTextBox; @@ -118,7 +120,7 @@ protected: /** * Process response data. Will disable selected options */ - void disableRespondedOptions(const LLNotificationPtr& notification); + //void disableRespondedOptions(const LLNotificationPtr& notification); bool mIsTip; bool mAddedDefaultBtn; @@ -137,13 +139,23 @@ class LLIMToastNotifyPanel : public LLToastNotifyPanel { public: - LLIMToastNotifyPanel(LLNotificationPtr& pNotification, const LLUUID& session_id, const LLRect& rect = LLRect::null, bool show_images = true); + LLIMToastNotifyPanel(LLNotificationPtr& pNotification, + const LLUUID& session_id, + const LLRect& rect = LLRect::null, + bool show_images = true, + LLTextBase* parent_text = NULL); + + void compactButtons(); + + virtual void updateNotification(); + virtual void init( LLRect rect, bool show_images ); ~LLIMToastNotifyPanel(); /*virtual*/ void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE); protected: + LLTextBase* mParentText; LLUUID mSessionID; }; diff --git a/indra/newview/lltoastpanel.cpp b/indra/newview/lltoastpanel.cpp index d2a4ce8745..e20d516392 100644 --- a/indra/newview/lltoastpanel.cpp +++ b/indra/newview/lltoastpanel.cpp @@ -78,11 +78,14 @@ void LLToastPanel::snapToMessageHeight(LLTextBase* message, S32 maxLineCount) S32 requiredTextHeight = message->getTextBoundingRect().getHeight(); S32 newTextHeight = llmin(requiredTextHeight, maxTextHeight); - //Calculate last delta height deducting previous heightDelta - heightDelta = newTextHeight - oldTextHeight - heightDelta; + heightDelta = newTextHeight - oldTextHeight; + S32 new_panel_height = llmax(getRect().getHeight() + heightDelta, MIN_PANEL_HEIGHT); //reshape the panel with new height - reshape( getRect().getWidth(), llmax(getRect().getHeight() + heightDelta, MIN_PANEL_HEIGHT)); + if (new_panel_height != getRect().getHeight()) + { + reshape( getRect().getWidth(), new_panel_height); + } } } @@ -96,7 +99,7 @@ LLToastPanel* LLToastPanel::buidPanelFromNotification( if ("notifytip" == notification->getType()) { // if it is online/offline notification - if ("FriendOffline" == notification->getName() || "FriendOnline" == notification->getName()) + if ("FriendOnlineOffline" == notification->getName()) { res = new LLPanelOnlineStatus(notification); } diff --git a/indra/newview/lltoastpanel.h b/indra/newview/lltoastpanel.h index 346e014d73..c22557206b 100644 --- a/indra/newview/lltoastpanel.h +++ b/indra/newview/lltoastpanel.h @@ -33,19 +33,13 @@ #include <string> -class LLToastPanelBase: public LLPanel -{ -public: - virtual void init(LLSD& data){}; -}; - /** * Base class for all panels that can be added to the toast. * All toast panels should contain necessary logic for representing certain notification * but shouldn't contain logic related to this panel lifetime control and positioning * on the parent view. */ -class LLToastPanel: public LLPanel { +class LLToastPanel : public LLPanel { public: LLToastPanel(const LLNotificationPtr&); virtual ~LLToastPanel() = 0; diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index c2bafd043d..cefd9ef91d 100755 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -179,6 +179,7 @@ bool friendship_offer_callback(const LLSD& notification, const LLSD& response) S32 option = LLNotificationsUtil::getSelectedOption(notification, response); LLMessageSystem* msg = gMessageSystem; const LLSD& payload = notification["payload"]; + LLNotificationPtr notification_ptr = LLNotifications::instance().find(notification["id"].asUUID()); // add friend to recent people list LLRecentPeople::instance().add(payload["from_id"]); @@ -204,7 +205,6 @@ bool friendship_offer_callback(const LLSD& notification, const LLSD& response) msg->sendReliable(LLHost(payload["sender"].asString())); LLSD payload = notification["payload"]; - payload["SUPPRESS_TOAST"] = true; LLNotificationsUtil::add("FriendshipAcceptedByMe", notification["substitutions"], payload); break; @@ -212,7 +212,6 @@ bool friendship_offer_callback(const LLSD& notification, const LLSD& response) case 1: // Decline { LLSD payload = notification["payload"]; - payload["SUPPRESS_TOAST"] = true; LLNotificationsUtil::add("FriendshipDeclinedByMe", notification["substitutions"], payload); } @@ -241,6 +240,12 @@ bool friendship_offer_callback(const LLSD& notification, const LLSD& response) break; } + LLNotificationFormPtr modified_form(new LLNotificationForm(*notification_ptr->getForm())); + modified_form->setElementEnabled("Accept", false); + modified_form->setElementEnabled("Decline", false); + notification_ptr->updateForm(modified_form); + notification_ptr->repost(); + return false; } static LLNotificationFunctorRegistration friendship_offer_callback_reg("OfferFriendship", friendship_offer_callback); @@ -1471,16 +1476,16 @@ bool LLOfferInfo::inventory_offer_callback(const LLSD& notification, const LLSD& itemp = (LLViewerInventoryItem*)gInventory.getItem(mObjectID); } + LLNotificationPtr notification_ptr = LLNotifications::instance().find(notification["id"].asUUID()); + llassert(notification_ptr != NULL); + // For muting, we need to add the mute, then decline the offer. // This must be done here because: // * callback may be called immediately, // * adding the mute sends a message, // * we can't build two messages at once. - if (2 == button) // Block + if (IOR_MUTE == button) // Block { - LLNotificationPtr notification_ptr = LLNotifications::instance().find(notification["id"].asUUID()); - - llassert(notification_ptr != NULL); if (notification_ptr != NULL) { gCacheName->get(mFromID, mFromGroup, boost::bind(&inventory_offer_mute_callback, _1, _2, _3)); @@ -1495,6 +1500,8 @@ bool LLOfferInfo::inventory_offer_callback(const LLSD& notification, const LLSD& bool busy = gAgent.getBusy(); + LLNotificationFormPtr modified_form(new LLNotificationForm(*notification_ptr->getForm())); + switch(button) { case IOR_SHOW: @@ -1538,6 +1545,8 @@ bool LLOfferInfo::inventory_offer_callback(const LLSD& notification, const LLSD& LL_WARNS("Messaging") << "inventory_offer_callback: unknown offer type" << LL_ENDL; break; } + + modified_form->setElementEnabled("Show", false); break; // end switch (mIM) @@ -1550,9 +1559,11 @@ bool LLOfferInfo::inventory_offer_callback(const LLSD& notification, const LLSD& args["MESSAGE"] = log_message; LLNotificationsUtil::add("SystemMessageTip", args); } + break; case IOR_MUTE: + modified_form->setElementEnabled("Mute", false); // MUTE falls through to decline case IOR_DECLINE: { @@ -1588,6 +1599,10 @@ bool LLOfferInfo::inventory_offer_callback(const LLSD& notification, const LLSD& { busy_message(gMessageSystem, mFromID); } + + modified_form->setElementEnabled("Show", false); + modified_form->setElementEnabled("Discard", false); + break; } default: @@ -1607,6 +1622,10 @@ bool LLOfferInfo::inventory_offer_callback(const LLSD& notification, const LLSD& { delete this; } + + notification_ptr->updateForm(modified_form); + notification_ptr->repost(); + return false; } @@ -1984,6 +2003,15 @@ bool lure_callback(const LLSD& notification, const LLSD& response) lure_id); break; } + + LLNotificationPtr notification_ptr = LLNotifications::instance().find(notification["id"].asUUID()); + + LLNotificationFormPtr modified_form(new LLNotificationForm(*notification_ptr->getForm())); + modified_form->setElementEnabled("Teleport", false); + modified_form->setElementEnabled("Cancel", false); + notification_ptr->updateForm(modified_form); + notification_ptr->repost(); + return false; } static LLNotificationFunctorRegistration lure_callback_reg("TeleportOffered", lure_callback); @@ -6394,7 +6422,6 @@ bool handle_lure_callback(const LLSD& notification, const LLSD& response) //*TODO please rewrite all keys to the same case, lower or upper payload["from_id"] = target_id; - payload["SUPPRESS_TOAST"] = true; LLNotificationsUtil::add("TeleportOfferSent", args, payload); // Add the recepient to the recent people list. diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml index d35cebbd16..5b7222c180 100644 --- a/indra/newview/skins/default/xui/en/notifications.xml +++ b/indra/newview/skins/default/xui/en/notifications.xml @@ -5208,20 +5208,14 @@ Topic: [SUBJECT], Message: [MESSAGE] <notification icon="notifytip.tga" - name="FriendOnline" + name="FriendOnlineOffline" log_to_chat="false" type="notifytip"> <tag>friendship</tag> -<nolink>[NAME]</nolink> is Online - </notification> - - <notification - icon="notifytip.tga" - name="FriendOffline" - log_to_chat="false" - type="notifytip"> - <tag>friendship</tag> -<nolink>[NAME]</nolink> is Offline +<nolink>[NAME]</nolink> is [STATUS] + <unique combine="cancel_old"> + <context>NAME</context> + </unique> </notification> <notification @@ -6160,7 +6154,8 @@ Your object named <nolink>[OBJECTFROMNAME]</nolink> has given you th <notification icon="notify.tga" name="TeleportOfferSent" - log_to_im="true" + log_to_im="true" + show_toast="false" type="offer"> Teleport offer sent to [TO_NAME] </notification> @@ -6213,6 +6208,7 @@ Your object named <nolink>[OBJECTFROMNAME]</nolink> has given you th icon="notify.tga" name="FriendshipOffered" log_to_im="true" + show_toast="false" type="offer"> <tag>friendship</tag> You have offered friendship to [TO_NAME] @@ -6262,6 +6258,7 @@ Your object named <nolink>[OBJECTFROMNAME]</nolink> has given you th icon="notify.tga" name="FriendshipAcceptedByMe" log_to_im="true" + show_toast="false" type="offer"> <tag>friendship</tag> Friendship offer accepted. @@ -6271,6 +6268,7 @@ Friendship offer accepted. icon="notify.tga" name="FriendshipDeclinedByMe" log_to_im="true" + show_toast="false" type="offer"> <tag>friendship</tag> Friendship offer declined. diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml index 0beb8ed0ab..d7bc998b36 100644 --- a/indra/newview/skins/default/xui/en/strings.xml +++ b/indra/newview/skins/default/xui/en/strings.xml @@ -3243,6 +3243,8 @@ If you continue to receive this message, contact the [SUPPORT_SITE]. <string name="IM_moderator_label">(Moderator)</string> <string name="Saved_message">(Saved [LONG_TIMESTAMP])</string> <string name="IM_unblock_only_groups_friends">To see this message, you must uncheck 'Only friends and groups can call or IM me' in Preferences/Privacy.</string> + <string name="OnlineStatus">Online</string> + <string name="OfflineStatus">Offline</string> <!-- voice calls --> <string name="answered_call">Your call has been answered</string> |