diff options
Diffstat (limited to 'indra/newview/llchathistory.cpp')
-rw-r--r-- | indra/newview/llchathistory.cpp | 207 |
1 files changed, 194 insertions, 13 deletions
diff --git a/indra/newview/llchathistory.cpp b/indra/newview/llchathistory.cpp index a46cd84b60..929457046c 100644 --- a/indra/newview/llchathistory.cpp +++ b/indra/newview/llchathistory.cpp @@ -34,7 +34,9 @@ #include "llinstantmessage.h" +#include "llimview.h" #include "llchathistory.h" +#include "llcommandhandler.h" #include "llpanel.h" #include "lluictrlfactory.h" #include "llscrollcontainer.h" @@ -46,8 +48,17 @@ #include "llfloaterreg.h" #include "llmutelist.h" #include "llstylemap.h" +#include "llslurl.h" #include "lllayoutstack.h" #include "llagent.h" +#include "llnotificationsutil.h" +#include "lltoastnotifypanel.h" +#include "lltooltip.h" +#include "llviewerregion.h" +#include "llviewertexteditor.h" +#include "llworld.h" +#include "lluiconstants.h" + #include "llsidetray.h"//for blocked objects panel @@ -55,6 +66,38 @@ static LLDefaultChildRegistry::Register<LLChatHistory> r("chat_history"); const static std::string NEW_LINE(rawstr_to_utf8("\n")); +// support for secondlife:///app/objectim/{UUID}/ SLapps +class LLObjectIMHandler : public LLCommandHandler +{ +public: + // requests will be throttled from a non-trusted browser + LLObjectIMHandler() : LLCommandHandler("objectim", UNTRUSTED_THROTTLE) {} + + bool handle(const LLSD& params, const LLSD& query_map, LLMediaCtrl* web) + { + if (params.size() < 1) + { + return false; + } + + LLUUID object_id; + if (!object_id.set(params[0], FALSE)) + { + return false; + } + + LLSD payload; + payload["object_id"] = object_id; + payload["owner_id"] = query_map["owner"]; + payload["name"] = query_map["name"]; + payload["slurl"] = query_map["slurl"]; + payload["group_owned"] = query_map["groupowned"]; + LLFloaterReg::showInstance("inspect_remote_object", payload); + return true; + } +}; +LLObjectIMHandler gObjectIMHandler; + class LLChatHistoryHeader: public LLPanel { public: @@ -70,6 +113,34 @@ public: return LLPanel::handleMouseUp(x,y,mask); } + //*TODO remake it using mouse enter/leave and static LLHandle<LLIconCtrl> to add/remove as a child + BOOL handleToolTip(S32 x, S32 y, MASK mask) + { + LLViewerTextEditor* name = getChild<LLViewerTextEditor>("user_name"); + if (name && name->parentPointInView(x, y) && mAvatarID.notNull() && SYSTEM_FROM != mFrom) + { + + // Spawn at right side of the name textbox. + LLRect sticky_rect = name->calcScreenRect(); + S32 icon_x = llmin(sticky_rect.mLeft + name->getTextBoundingRect().getWidth() + 7, sticky_rect.mRight - 3); + + LLToolTip::Params params; + params.background_visible(false); + params.click_callback(boost::bind(&LLChatHistoryHeader::onHeaderPanelClick, this, 0, 0, 0)); + params.delay_time(0.0f); // spawn instantly on hover + params.image(LLUI::getUIImage("Info_Small")); + params.message(""); + params.padding(0); + params.pos(LLCoordGL(icon_x, sticky_rect.mTop - 2)); + params.sticky_rect(sticky_rect); + + LLToolTipMgr::getInstance()->show(params); + return TRUE; + } + + return LLPanel::handleToolTip(x, y, mask); + } + void onObjectIconContextMenuItemClicked(const LLSD& userdata) { std::string level = userdata.asString(); @@ -183,6 +254,7 @@ public: void setup(const LLChat& chat,const LLStyle::Params& style_params) { mAvatarID = chat.mFromID; + mSessionID = chat.mSessionID; mSourceType = chat.mSourceType; gCacheName->get(mAvatarID, FALSE, boost::bind(&LLChatHistoryHeader::nameUpdatedCallback, this, _1, _2, _3, _4)); if(chat.mFromID.isNull()) @@ -190,7 +262,7 @@ public: mSourceType = CHAT_SOURCE_SYSTEM; } - LLTextEditor* userName = getChild<LLTextEditor>("user_name"); + LLTextBox* userName = getChild<LLTextBox>("user_name"); userName->setReadOnlyColor(style_params.readonly_color()); userName->setColor(style_params.color()); @@ -228,7 +300,7 @@ public: /*virtual*/ void draw() { - LLTextEditor* user_name = getChild<LLTextEditor>("user_name"); + LLTextBox* user_name = getChild<LLTextBox>("user_name"); LLTextBox* time_box = getChild<LLTextBox>("time_box"); LLRect user_name_rect = user_name->getRect(); @@ -272,7 +344,7 @@ protected: showSystemContextMenu(x,y); if(mSourceType == CHAT_SOURCE_AGENT) showAvatarContextMenu(x,y); - if(mSourceType == CHAT_SOURCE_OBJECT) + if(mSourceType == CHAT_SOURCE_OBJECT && SYSTEM_FROM != mFrom) showObjectContextMenu(x,y); } @@ -305,6 +377,11 @@ protected: menu->setItemEnabled("Remove Friend", false); } + if (mSessionID == LLIMMgr::computeSessionID(IM_NOTHING_SPECIAL, mAvatarID)) + { + menu->setItemVisible("Send IM", false); + } + menu->buildDrawLabels(); menu->updateParent(LLMenuGL::sMenuContainer); LLMenuGL::showPopup(this, menu, x, y); @@ -344,6 +421,7 @@ protected: std::string mFirstName; std::string mLastName; std::string mFrom; + LLUUID mSessionID; S32 mMinUserNameWidth; }; @@ -366,6 +444,7 @@ LLChatHistory::LLChatHistory(const LLChatHistory::Params& p) editor_params.rect = getLocalRect(); editor_params.follows.flags = FOLLOWS_ALL; editor_params.enabled = false; // read only + editor_params.show_context_menu = "true"; mEditor = LLUICtrlFactory::create<LLTextEditor>(editor_params, this); } @@ -457,8 +536,9 @@ void LLChatHistory::clear() mLastFromID = LLUUID::null; } -void LLChatHistory::appendMessage(const LLChat& chat, const bool use_plain_text_chat_history, const LLStyle::Params& input_append_params) +void LLChatHistory::appendMessage(const LLChat& chat, const LLSD &args, const LLStyle::Params& input_append_params) { + bool use_plain_text_chat_history = args["use_plain_text_chat_history"].asBoolean(); if (!mEditor->scrolledToEnd() && chat.mFromID != gAgent.getID() && !chat.mFromName.empty()) { mUnreadChatSources.insert(chat.mFromName); @@ -470,7 +550,7 @@ void LLChatHistory::appendMessage(const LLChat& chat, const bool use_plain_text_ chatters += *it; if (++it != mUnreadChatSources.end()) { - chatters += ","; + chatters += ", "; } } LLStringUtil::format_map_t args; @@ -506,9 +586,16 @@ void LLChatHistory::appendMessage(const LLChat& chat, const bool use_plain_text_ bool irc_me = prefix == "/me " || prefix == "/me'"; // Delimiter after a name in header copy/past and in plain text mode - std::string delimiter = (chat.mChatType != CHAT_TYPE_SHOUT && chat.mChatType != CHAT_TYPE_WHISPER) - ? ": " - : " "; + std::string delimiter = ": "; + std::string shout = LLTrans::getString("shout"); + std::string whisper = LLTrans::getString("whisper"); + if (chat.mChatType == CHAT_TYPE_SHOUT || + chat.mChatType == CHAT_TYPE_WHISPER || + chat.mText.compare(0, shout.length(), shout) == 0 || + chat.mText.compare(0, whisper.length(), whisper) == 0) + { + delimiter = " "; + } // Don't add any delimiter after name in irc styled messages if (irc_me || chat.mChatStyle == CHAT_STYLE_IRC) @@ -524,7 +611,35 @@ void LLChatHistory::appendMessage(const LLChat& chat, const bool use_plain_text_ if (utf8str_trim(chat.mFromName).size() != 0) { // Don't hotlink any messages from the system (e.g. "Second Life:"), so just add those in plain text. - if ( chat.mFromName != SYSTEM_FROM && chat.mFromID.notNull() ) + if ( chat.mSourceType == CHAT_SOURCE_OBJECT ) + { + // for object IMs, create a secondlife:///app/objectim SLapp + std::string url = LLSLURL::buildCommand("objectim", chat.mFromID, ""); + url += "?name=" + chat.mFromName; + url += "&owner=" + args["owner_id"].asString(); + + std::string slurl = args["slurl"].asString(); + if (slurl.empty()) + { + LLViewerRegion *region = LLWorld::getInstance()->getRegionFromPosAgent(chat.mPosAgent); + if (region) + { + S32 x, y, z; + LLSLURL::globalPosToXYZ(LLVector3d(chat.mPosAgent), x, y, z); + slurl = region->getName() + llformat("/%d/%d/%d", x, y, z); + } + } + url += "&slurl=" + slurl; + + // set the link for the object name to be the objectim SLapp + // (don't let object names with hyperlinks override our objectim Url) + LLStyle::Params link_params(style_params); + link_params.color.control = "HTMLLinkColor"; + link_params.link_href = url; + mEditor->appendText("<nolink>" + chat.mFromName + "</nolink>" + delimiter, + false, link_params); + } + else if ( chat.mFromName != SYSTEM_FROM && chat.mFromID.notNull() ) { LLStyle::Params link_params(style_params); link_params.fillFrom(LLStyleMap::instance().lookupAgent(chat.mFromID)); @@ -550,8 +665,8 @@ void LLChatHistory::appendMessage(const LLChat& chat, const bool use_plain_text_ if (mLastFromName == chat.mFromName && mLastFromID == chat.mFromID && mLastMessageTime.notNull() - && (new_message_time.secondsSinceEpoch() - mLastMessageTime.secondsSinceEpoch()) < 60.0 - ) + && (new_message_time.secondsSinceEpoch() - mLastMessageTime.secondsSinceEpoch()) < 60.0 + && mLastMessageTimeStr.size() == chat.mTimeStr.size()) //*HACK to distinguish between current and previous chat session's histories { view = getSeparator(); p.top_pad = mTopSeparatorPad; @@ -585,10 +700,76 @@ void LLChatHistory::appendMessage(const LLChat& chat, const bool use_plain_text_ mLastFromName = chat.mFromName; mLastFromID = chat.mFromID; mLastMessageTime = new_message_time; + mLastMessageTimeStr = chat.mTimeStr; } - std::string message = irc_me ? chat.mText.substr(3) : chat.mText; - mEditor->appendText(message, FALSE, style_params); + if (chat.mNotifId.notNull()) + { + LLNotificationPtr notification = LLNotificationsUtil::find(chat.mNotifId); + if (notification != NULL) + { + LLToastNotifyPanel* notify_box = new LLToastNotifyPanel( + notification); + //we can't set follows in xml since it broke toasts behavior + notify_box->setFollowsLeft(); + notify_box->setFollowsRight(); + notify_box->setFollowsTop(); + + LLButton* accept_button = notify_box->getChild<LLButton> ("Accept", + TRUE); + if (accept_button != NULL) + { + accept_button->setFollowsNone(); + accept_button->setOrigin(2*HPAD, accept_button->getRect().mBottom); + } + + LLButton* decline_button = notify_box->getChild<LLButton> ( + "Decline", TRUE); + if (accept_button != NULL && decline_button != NULL) + { + decline_button->setFollowsNone(); + decline_button->setOrigin(4*HPAD + + accept_button->getRect().getWidth(), + decline_button->getRect().mBottom); + } + + LLTextEditor* text_editor = notify_box->getChild<LLTextEditor>("text_editor_box", TRUE); + S32 text_heigth = 0; + if(text_editor != NULL) + { + text_heigth = text_editor->getTextBoundingRect().getHeight(); + } + + //Prepare the rect for the view + LLRect target_rect = mEditor->getDocumentView()->getRect(); + // squeeze down the widget by subtracting padding off left and right + target_rect.mLeft += mLeftWidgetPad + mEditor->getHPad(); + target_rect.mRight -= mRightWidgetPad; + notify_box->reshape(target_rect.getWidth(), + notify_box->getRect().getHeight()); + notify_box->setOrigin(target_rect.mLeft, notify_box->getRect().mBottom); + + if (text_editor != NULL) + { + S32 text_heigth_delta = + text_editor->getTextBoundingRect().getHeight() + - text_heigth; + notify_box->reshape(target_rect.getWidth(), + notify_box->getRect().getHeight() + text_heigth_delta); + } + + LLInlineViewSegment::Params params; + params.view = notify_box; + params.left_pad = mLeftWidgetPad; + params.right_pad = mRightWidgetPad; + mEditor->appendWidget(params, "\n", false); + } + } + else + { + std::string message = irc_me ? chat.mText.substr(3) : chat.mText; + mEditor->appendText(message, FALSE, style_params); + } mEditor->blockUndo(); // automatically scroll to end when receiving chat from myself |