diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp index e481e056f1679abe5f33d60ff1b4a999186dfd9b..17efeb2ffd47564088fc2f7df712a27dd8b6ee0e 100644 --- a/indra/newview/llfloaterimcontainer.cpp +++ b/indra/newview/llfloaterimcontainer.cpp @@ -586,6 +586,28 @@ void LLFloaterIMContainer::returnFloaterToHost() floater->onTearOffClicked(); } +void LLFloaterIMContainer::setMinimized(BOOL b) +{ + bool was_minimized = isMinimized(); + LLMultiFloater::setMinimized(b); + + //Switching from minimized to un-minimized + if(was_minimized && !b) + { + LLFloaterIMSessionTab* session_floater = LLFloaterIMSessionTab::findConversation(mSelectedSession); + + if(session_floater && !session_floater->isTornOff()) + { + //When in DND mode, remove stored IM notifications + //Nearby chat (Null) IMs are not stored while in DND mode, so can ignore removal + if(gAgent.isDoNotDisturb() && mSelectedSession.notNull()) + { + LLDoNotDisturbNotificationStorage::getInstance()->removeNotification(LLDoNotDisturbNotificationStorage::toastName, mSelectedSession); + } + } + } +} + void LLFloaterIMContainer::setVisible(BOOL visible) { LLFloaterIMNearbyChat* nearby_chat; if (visible) @@ -598,10 +620,21 @@ void LLFloaterIMContainer::setVisible(BOOL visible) // *TODO: find a way to move this to XML as a default panel or something like that LLSD name("nearby_chat"); LLFloaterReg::toggleInstanceOrBringToFront(name); - setSelectedSession(LLUUID(NULL)); + selectConversationPair(LLUUID(NULL), false, false); } openNearbyChat(); - selectConversationPair(getSelectedSession(), false, false); + flashConversationItemWidget(mSelectedSession,false); + + LLFloaterIMSessionTab* session_floater = LLFloaterIMSessionTab::findConversation(mSelectedSession); + if(session_floater && !session_floater->isMinimized()) + { + //When in DND mode, remove stored IM notifications + //Nearby chat (Null) IMs are not stored while in DND mode, so can ignore removal + if(gAgent.isDoNotDisturb() && mSelectedSession.notNull()) + { + LLDoNotDisturbNotificationStorage::getInstance()->removeNotification(LLDoNotDisturbNotificationStorage::toastName, mSelectedSession); + } + } } nearby_chat = LLFloaterReg::findTypedInstance<LLFloaterIMNearbyChat>("nearby_chat"); @@ -1179,7 +1212,8 @@ bool LLFloaterIMContainer::enableContextMenuItem(const LLSD& userdata) //Enable Chat history item for ad-hoc and group conversations if ("can_chat_history" == item && uuids.size() > 0) { - return LLLogChat::isTranscriptExist(uuids.front()); + bool is_group = (getCurSelectedViewModelItem()->getType() == LLConversationItem::CONV_SESSION_GROUP); + return LLLogChat::isTranscriptExist(uuids.front(),is_group); } // If nothing is selected(and selected item is not group chat), everything needs to be disabled @@ -1390,13 +1424,6 @@ BOOL LLFloaterIMContainer::selectConversationPair(const LLUUID& session_id, bool widget->getParentFolder()->setSelection(widget, FALSE, FALSE); mConversationsRoot->scrollToShowSelection(); } - - //When in DND mode, remove stored IM notifications - //Nearby chat (Null) IMs are not stored while in DND mode, so can ignore removal - if(gAgent.isDoNotDisturb() && session_id.notNull()) - { - LLDoNotDisturbNotificationStorage::getInstance()->removeNotification(LLDoNotDisturbNotificationStorage::toastName, session_id); - } } /* floater processing */ @@ -1421,14 +1448,19 @@ BOOL LLFloaterIMContainer::selectConversationPair(const LLUUID& session_id, bool { showStub(true); } + + //When in DND mode, remove stored IM notifications + //Nearby chat (Null) IMs are not stored while in DND mode, so can ignore removal + if(gAgent.isDoNotDisturb() && session_id.notNull()) + { + LLDoNotDisturbNotificationStorage::getInstance()->removeNotification(LLDoNotDisturbNotificationStorage::toastName, session_id); + } } // Set the focus on the selected floater - if (!session_floater->hasFocus()) + if (!session_floater->hasFocus() && !session_floater->isMinimized()) { - BOOL is_minimized = session_floater->isMinimized(); session_floater->setFocus(focus_floater); - session_floater->setMinimized(is_minimized); } } flashConversationItemWidget(session_id,false); @@ -1986,8 +2018,11 @@ void LLFloaterIMContainer::closeFloater(bool app_quitting/* = false*/) { // Always unminimize before trying to close. // Most of the time the user will never see this state. - setMinimized(FALSE); - + if(isMinimized()) + { + LLMultiFloater::setMinimized(FALSE); + } + LLFloater::closeFloater(app_quitting); } diff --git a/indra/newview/llfloaterimcontainer.h b/indra/newview/llfloaterimcontainer.h index 0890f694d957db80b3b7e33f41becddd74454bb5..2833f1e64646b05cc9686ec5c145622bd44f6172 100644 --- a/indra/newview/llfloaterimcontainer.h +++ b/indra/newview/llfloaterimcontainer.h @@ -59,6 +59,7 @@ class LLFloaterIMContainer /*virtual*/ BOOL postBuild(); /*virtual*/ void onOpen(const LLSD& key); /*virtual*/ void draw(); + /*virtual*/ void setMinimized(BOOL b); /*virtual*/ void setVisible(BOOL visible); /*virtual*/ void setVisibleAndFrontmost(BOOL take_focus=TRUE, const LLSD& key = LLSD()); /*virtual*/ void updateResizeLimits(); diff --git a/indra/newview/llfloaterimnearbychat.cpp b/indra/newview/llfloaterimnearbychat.cpp index 56b0c15cb9e8ec03157270f9ef3e45ec0d04b085..49f36a2f321b1b1152a4f4eddf680fb4fff8d84a 100644 --- a/indra/newview/llfloaterimnearbychat.cpp +++ b/indra/newview/llfloaterimnearbychat.cpp @@ -328,7 +328,7 @@ void LLFloaterIMNearbyChat::onChatFontChange(LLFontGL* fontp) void LLFloaterIMNearbyChat::show() { openFloater(getKey()); - } +} bool LLFloaterIMNearbyChat::isChatVisible() const { diff --git a/indra/newview/llfloaterimsession.cpp b/indra/newview/llfloaterimsession.cpp index 6d5145f205fc754fb43f1a3c35b0dbbaa85c94ea..edc25a7d7eca01ab55f8fed91a469331fa6f3a8d 100644 --- a/indra/newview/llfloaterimsession.cpp +++ b/indra/newview/llfloaterimsession.cpp @@ -39,6 +39,7 @@ #include "llchannelmanager.h" #include "llchiclet.h" #include "llchicletbar.h" +#include "lldonotdisturbnotificationstorage.h" #include "llfloaterreg.h" #include "llfloateravatarpicker.h" #include "llfloaterimcontainer.h" // to replace separate IM Floaters with multifloater container @@ -645,6 +646,23 @@ void LLFloaterIMSession::setDocked(bool docked, bool pop_on_undock) } } +void LLFloaterIMSession::setMinimized(BOOL b) +{ + bool wasMinimized = isMinimized(); + LLFloaterIMSessionTab::setMinimized(b); + + //Switching from minimized state to un-minimized state + if(wasMinimized && !b) + { + //When in DND mode, remove stored IM notifications + //Nearby chat (Null) IMs are not stored while in DND mode, so can ignore removal + if(gAgent.isDoNotDisturb()) + { + LLDoNotDisturbNotificationStorage::getInstance()->removeNotification(LLDoNotDisturbNotificationStorage::toastName, mSessionID); + } + } +} + void LLFloaterIMSession::setVisible(BOOL visible) { LLNotificationsUI::LLScreenChannel* channel = static_cast<LLNotificationsUI::LLScreenChannel*> @@ -713,6 +731,18 @@ BOOL LLFloaterIMSession::getVisible() return visible; } +void LLFloaterIMSession::setFocus(BOOL focus) +{ + LLFloaterIMSessionTab::setFocus(focus); + + //When in DND mode, remove stored IM notifications + //Nearby chat (Null) IMs are not stored while in DND mode, so can ignore removal + if(focus && gAgent.isDoNotDisturb()) + { + LLDoNotDisturbNotificationStorage::getInstance()->removeNotification(LLDoNotDisturbNotificationStorage::toastName, mSessionID); + } +} + //static bool LLFloaterIMSession::toggle(const LLUUID& session_id) { diff --git a/indra/newview/llfloaterimsession.h b/indra/newview/llfloaterimsession.h index cb330bca0f25baba9de25f04f702a32c103309aa..a0e0171b344baa322714bc3766e6851f499e7197 100644 --- a/indra/newview/llfloaterimsession.h +++ b/indra/newview/llfloaterimsession.h @@ -65,8 +65,10 @@ class LLFloaterIMSession // LLView overrides /*virtual*/ BOOL postBuild(); + /*virtual*/ void setMinimized(BOOL b); /*virtual*/ void setVisible(BOOL visible); /*virtual*/ BOOL getVisible(); + /*virtual*/ void setFocus(BOOL focus); // Check typing timeout timer. /*virtual*/ void draw(); diff --git a/indra/newview/llgroupactions.cpp b/indra/newview/llgroupactions.cpp index a0f2918bd786338340f7b9fa606c2021ef2323b2..302d21c2e42b16f24ca1b1ed628c412026b87280 100644 --- a/indra/newview/llgroupactions.cpp +++ b/indra/newview/llgroupactions.cpp @@ -116,6 +116,80 @@ class LLGroupHandler : public LLCommandHandler }; LLGroupHandler gGroupHandler; +// This object represents a pending request for specified group member information +// which is needed to check whether avatar can leave group +class LLFetchGroupMemberData : public LLGroupMgrObserver +{ +public: + LLFetchGroupMemberData(const LLUUID& group_id) : + mGroupId(group_id), + mRequestProcessed(false), + LLGroupMgrObserver(group_id) + { + llinfos << "Sending new group member request for group_id: "<< group_id << llendl; + LLGroupMgr* mgr = LLGroupMgr::getInstance(); + // register ourselves as an observer + mgr->addObserver(this); + // send a request + mgr->sendGroupPropertiesRequest(group_id); + mgr->sendCapGroupMembersRequest(group_id); + } + + ~LLFetchGroupMemberData() + { + if (!mRequestProcessed) + { + // Request is pending + llwarns << "Destroying pending group member request for group_id: " + << mGroupId << llendl; + } + // Remove ourselves as an observer + LLGroupMgr::getInstance()->removeObserver(this); + } + + void changed(LLGroupChange gc) + { + if (gc == GC_MEMBER_DATA && !mRequestProcessed) + { + LLGroupMgrGroupData* gdatap = LLGroupMgr::getInstance()->getGroupData(mGroupId); + if (!gdatap) + { + llwarns << "LLGroupMgr::getInstance()->getGroupData() was NULL" << llendl; + } + else if (!gdatap->isMemberDataComplete()) + { + llwarns << "LLGroupMgr::getInstance()->getGroupData()->isMemberDataComplete() was FALSE" << llendl; + } + else + { + processGroupData(); + mRequestProcessed = true; + } + } + } + + LLUUID getGroupId() { return mGroupId; } + virtual void processGroupData() = 0; +protected: + LLUUID mGroupId; +private: + bool mRequestProcessed; +}; + +class LLFetchLeaveGroupData: public LLFetchGroupMemberData +{ +public: + LLFetchLeaveGroupData(const LLUUID& group_id) + : LLFetchGroupMemberData(group_id) + {} + void processGroupData() + { + LLGroupActions::processLeaveGroupDataResponse(mGroupId); + } +}; + +LLFetchLeaveGroupData* gFetchLeaveGroupData = NULL; + // static void LLGroupActions::search() { @@ -208,23 +282,52 @@ bool LLGroupActions::onJoinGroup(const LLSD& notification, const LLSD& response) void LLGroupActions::leave(const LLUUID& group_id) { if (group_id.isNull()) + { return; + } - S32 count = gAgent.mGroups.count(); - S32 i; - for (i = 0; i < count; ++i) + LLGroupData group_data; + if (gAgent.getGroupData(group_id, group_data)) { - if(gAgent.mGroups.get(i).mID == group_id) - break; + LLGroupMgrGroupData* gdatap = LLGroupMgr::getInstance()->getGroupData(group_id); + if (!gdatap || !gdatap->isMemberDataComplete()) + { + if (gFetchLeaveGroupData != NULL) + { + delete gFetchLeaveGroupData; + gFetchLeaveGroupData = NULL; + } + gFetchLeaveGroupData = new LLFetchLeaveGroupData(group_id); + } + else + { + processLeaveGroupDataResponse(group_id); + } } - if (i < count) +} + +//static +void LLGroupActions::processLeaveGroupDataResponse(const LLUUID group_id) +{ + LLGroupMgrGroupData* gdatap = LLGroupMgr::getInstance()->getGroupData(group_id); + LLUUID agent_id = gAgent.getID(); + LLGroupMgrGroupData::member_list_t::iterator mit = gdatap->mMembers.find(agent_id); + //get the member data for the group + if ( mit != gdatap->mMembers.end() ) { - LLSD args; - args["GROUP"] = gAgent.mGroups.get(i).mName; - LLSD payload; - payload["group_id"] = group_id; - LLNotificationsUtil::add("GroupLeaveConfirmMember", args, payload, onLeaveGroup); + LLGroupMemberData* member_data = (*mit).second; + + if ( member_data && member_data->isOwner() && gdatap->mMemberCount == 1) + { + LLNotificationsUtil::add("OwnerCannotLeaveGroup"); + return; + } } + LLSD args; + args["GROUP"] = gdatap->mName; + LLSD payload; + payload["group_id"] = group_id; + LLNotificationsUtil::add("GroupLeaveConfirmMember", args, payload, onLeaveGroup); } // static diff --git a/indra/newview/llgroupactions.h b/indra/newview/llgroupactions.h index 3f9852f194550d302aa2db12c2002c431c50412f..afc4686dd77c00fcda9d9ecd8b759b07b0cc52fd 100644 --- a/indra/newview/llgroupactions.h +++ b/indra/newview/llgroupactions.h @@ -114,6 +114,14 @@ class LLGroupActions private: static bool onJoinGroup(const LLSD& notification, const LLSD& response); static bool onLeaveGroup(const LLSD& notification, const LLSD& response); + + /** + * This function is called by LLFetchLeaveGroupData upon receiving a response to a group + * members data request. + */ + static void processLeaveGroupDataResponse(const LLUUID group_id); + + friend class LLFetchLeaveGroupData; }; #endif // LL_LLGROUPACTIONS_H diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index 141d43c6083d1ffe43f7df86d2c53adad74f89f4..afac94af07c3e4a2c34d17026a71bb1f258496a0 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -182,18 +182,19 @@ void on_new_message(const LLSD& msg) { conversations_floater_status = CLOSED; } - else if (!session_floater || !LLFloater::isVisible(session_floater) - || session_floater->isMinimized() || !session_floater->hasFocus()) + else if (!im_box->hasFocus() && + !(session_floater && LLFloater::isVisible(session_floater) + && !session_floater->isMinimized() && session_floater->hasFocus())) { conversations_floater_status = NOT_ON_TOP; } - else if ((session_floater->hasFocus()) && (im_box->getSelectedSession() == session_id)) + else if (im_box->getSelectedSession() != session_id) { - conversations_floater_status = ON_TOP_AND_ITEM_IS_SELECTED; + conversations_floater_status = ON_TOP; } else { - conversations_floater_status = ON_TOP; + conversations_floater_status = ON_TOP_AND_ITEM_IS_SELECTED; } // determine user prefs for this session @@ -226,7 +227,7 @@ void on_new_message(const LLSD& msg) // 0. nothing - exit if (("none" == user_preferences || ON_TOP_AND_ITEM_IS_SELECTED == conversations_floater_status) - && session_floater->isMessagePaneExpanded()) + && session_floater->isMessagePaneExpanded()) { return; } diff --git a/indra/newview/lllogchat.cpp b/indra/newview/lllogchat.cpp index 2d7454b636b2254b512c3907ff9debf80285fc26..82409da4baf6e69cfb95ca4f87ee8d1a52855271 100644 --- a/indra/newview/lllogchat.cpp +++ b/indra/newview/lllogchat.cpp @@ -631,7 +631,7 @@ void LLLogChat::deleteTranscripts() } // static -bool LLLogChat::isTranscriptExist(const LLUUID& avatar_id) +bool LLLogChat::isTranscriptExist(const LLUUID& avatar_id, bool is_group) { std::vector<std::string> list_of_transcriptions; LLLogChat::getListOfTranscriptFiles(list_of_transcriptions); @@ -641,15 +641,31 @@ bool LLLogChat::isTranscriptExist(const LLUUID& avatar_id) LLAvatarName avatar_name; LLAvatarNameCache::get(avatar_id, &avatar_name); std::string avatar_user_name = avatar_name.getAccountName(); - std::replace(avatar_user_name.begin(), avatar_user_name.end(), '.', '_'); - - BOOST_FOREACH(std::string& transcript_file_name, list_of_transcriptions) + if(!is_group) { - if (std::string::npos != transcript_file_name.find(avatar_user_name)) + std::replace(avatar_user_name.begin(), avatar_user_name.end(), '.', '_'); + BOOST_FOREACH(std::string& transcript_file_name, list_of_transcriptions) { - return true; + if (std::string::npos != transcript_file_name.find(avatar_user_name)) + { + return true; + } } } + else + { + std::string file_name; + gCacheName->getGroupName(avatar_id, file_name); + file_name = makeLogFileName(file_name); + BOOST_FOREACH(std::string& transcript_file_name, list_of_transcriptions) + { + if (transcript_file_name == file_name) + { + return true; + } + } + } + } return false; diff --git a/indra/newview/lllogchat.h b/indra/newview/lllogchat.h index e819f00dd9c5f6e3cea756a24ddcc3c521fe2995..77bb2a1570b6e3e6145e08596ae83a21f8b482c6 100644 --- a/indra/newview/lllogchat.h +++ b/indra/newview/lllogchat.h @@ -67,7 +67,7 @@ class LLLogChat std::vector<std::string>& listOfFilesToMove); static void deleteTranscripts(); - static bool isTranscriptExist(const LLUUID& avatar_id); + static bool isTranscriptExist(const LLUUID& avatar_id, bool is_group=false); private: static std::string cleanFileName(std::string filename); diff --git a/indra/newview/lltoastimpanel.cpp b/indra/newview/lltoastimpanel.cpp index 75e6e3d13a4a3b07e24e6fa1b40d0fe6042442df..025ef3945d1372539f601014b010011bbb79cc8e 100644 --- a/indra/newview/lltoastimpanel.cpp +++ b/indra/newview/lltoastimpanel.cpp @@ -28,6 +28,7 @@ #include "lltoastimpanel.h" #include "llagent.h" +#include "llavatarnamecache.h" #include "llfloaterreg.h" #include "llgroupactions.h" #include "llgroupiconctrl.h" @@ -61,6 +62,15 @@ LLToastIMPanel::LLToastIMPanel(LLToastIMPanel::Params &p) : LLToastPanel(p.notif style_params.font.name(font_name); style_params.font.size(font_size); + LLIMModel::LLIMSession* im_session = LLIMModel::getInstance()->findIMSession(p.session_id); + mIsGroupMsg = (im_session->mSessionType == LLIMModel::LLIMSession::GROUP_SESSION); + if(mIsGroupMsg) + { + mAvatarName->setValue(im_session->mName); + LLAvatarName avatar_name; + LLAvatarNameCache::get(p.avatar_id, &avatar_name); + p.message = "[From " + avatar_name.getDisplayName() + "]\n" + p.message; + } //Handle IRC styled /me messages. std::string prefix = p.message.substr(0, 4); @@ -81,12 +91,17 @@ LLToastIMPanel::LLToastIMPanel(LLToastIMPanel::Params &p) : LLToastPanel(p.notif mMessage->setText(p.message, style_params); } - mAvatarName->setValue(p.from); + if(!mIsGroupMsg) + { + mAvatarName->setValue(p.from); + } mTime->setValue(p.time); mSessionID = p.session_id; mAvatarID = p.avatar_id; mNotification = p.notification; + + initIcon(); S32 maxLinesCount; @@ -147,7 +162,14 @@ void LLToastIMPanel::spawnNameToolTip() LLToolTip::Params params; params.background_visible(false); - params.click_callback(boost::bind(&LLFloaterReg::showInstance, "inspect_avatar", LLSD().with("avatar_id", mAvatarID), FALSE)); + if(!mIsGroupMsg) + { + params.click_callback(boost::bind(&LLFloaterReg::showInstance, "inspect_avatar", LLSD().with("avatar_id", mAvatarID), FALSE)); + } + else + { + params.click_callback(boost::bind(&LLFloaterReg::showInstance, "inspect_group", LLSD().with("group_id", mSessionID), FALSE)); + } params.delay_time(0.0f); // spawn instantly on hover params.image(LLUI::getUIImage("Info_Small")); params.message(""); diff --git a/indra/newview/lltoastimpanel.h b/indra/newview/lltoastimpanel.h index 3eb11fb3bc6e157c1004036c43afa0502927c7f4..767617dabca83a746bd780f1392cc33161a39a83 100644 --- a/indra/newview/lltoastimpanel.h +++ b/indra/newview/lltoastimpanel.h @@ -73,6 +73,8 @@ class LLToastIMPanel: public LLToastPanel LLTextBox* mAvatarName; LLTextBox* mTime; LLTextBox* mMessage; + + bool mIsGroupMsg; }; #endif // LLTOASTIMPANEL_H_ diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index 4afd90b44c016fea130eba705047782ab2bbb1eb..be508ad17d5b46cf22c89ed79e19ed77255e12ac 100755 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -1798,9 +1798,7 @@ void LLViewerWindow::initBase() // Constrain floaters to inside the menu and status bar regions. gFloaterView = main_view->getChild<LLFloaterView>("Floater View"); - gFloaterView->setFloaterSnapView(main_view->getChild<LLView>("floater_snap_region")->getHandle()); gSnapshotFloaterView = main_view->getChild<LLSnapshotFloaterView>("Snapshot Floater View"); - // Console llassert( !gConsole ); diff --git a/indra/newview/skins/default/xui/en/floater_im_session.xml b/indra/newview/skins/default/xui/en/floater_im_session.xml index 3b56e974d21dadbc2a70b0fe17a82b9742b73071..08ecc37d21603febfe038279caf135ae1548ccfd 100644 --- a/indra/newview/skins/default/xui/en/floater_im_session.xml +++ b/indra/newview/skins/default/xui/en/floater_im_session.xml @@ -70,23 +70,27 @@ top="0" left="0" right="-1" - bottom="-1"> + bottom="-3"> <layout_stack animate="false" default_tab_group="2" follows="all" right="-5" bottom="-1" + top="0" + left="3" + border_size="0" layout="topleft" orientation="vertical" name="main_stack" - tab_group="1" - top="0" - left="5"> + tab_group="1"> <layout_panel auto_resize="false" + user_resize="false" name="toolbar_panel" - height="35"> + height="35" + right="-1" + left="1"> <menu_button menu_filename="menu_im_session_showmodes.xml" follows="top|left" @@ -164,7 +168,7 @@ image_unselected="Toolbar_Middle_Off" layout="topleft" top="5" - right="-70" + right="-67" name="close_btn" tool_tip="End this conversation" width="31" /> @@ -196,7 +200,10 @@ </layout_panel> <layout_panel name="body_panel" - height="235"> + top="1" + bottom="-1" + auto_resize="true" + user_resize="false"> <layout_stack default_tab_group="2" follows="all" @@ -213,12 +220,14 @@ min_dim="0" width="150" user_resize="true" - auto_resize="false" /> + auto_resize="false" + bottom="-1" /> <layout_panel default_tab_group="3" tab_group="2" name="right_part_holder" - min_width="221"> + min_width="221" + bottom="-1"> <layout_stack animate="true" default_tab_group="2" @@ -262,21 +271,29 @@ </layout_stack> </layout_panel> <layout_panel - height="35" + top_delta="0" + top="0" + height="26" + bottom="-1" auto_resize="false" + user_resize="false" name="chat_layout_panel"> <layout_stack animate="false" default_tab_group="2" follows="all" - right="-1" orientation="horizontal" name="input_panels" top="0" - bottom="-1" - left="0"> + bottom="-2" + left="0" + right="-1"> <layout_panel - name="input_editor_layout_panel"> + name="input_editor_layout_panel" + auto_resize="true" + user_resize="false" + top="0" + bottom="-1"> <chat_editor layout="topleft" expand_lines_count="5" @@ -289,27 +306,32 @@ max_length="1023" spellcheck="true" tab_group="3" - bottom="-8" - left="5" - right="-5" + top="1" + bottom="-2" + left="4" + right="-4" wrap="true" /> </layout_panel> <layout_panel auto_resize="false" + user_resize="false" name="input_button_layout_panel" - width="32"> + width="30" + top="0" + bottom="-1"> <button + layout="topleft" left="1" - top="4" + right="-1" + top="1" + height="22" follows="left|right|top" - height="25" image_hover_unselected="Toolbar_Middle_Over" image_overlay="Conv_expand_one_line" image_selected="Toolbar_Middle_Selected" image_unselected="Toolbar_Middle_Off" name="minz_btn" - tool_tip="Shows/hides message panel" - width="28" /> + tool_tip="Shows/hides message panel" /> </layout_panel> </layout_stack> </layout_panel> diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml index 105bef7321aec94bcb0e5b2394bd7e6c531c24e7..49e2ddfb1477f2aab3b68c2a54e1232aee61ef75 100644 --- a/indra/newview/skins/default/xui/en/notifications.xml +++ b/indra/newview/skins/default/xui/en/notifications.xml @@ -3648,6 +3648,17 @@ Leave Group? yestext="OK"/> </notification> + <notification + icon="alertmodal.tga" + name="OwnerCannotLeaveGroup" + type="alertmodal"> + Unable to leave group. You cannot leave the group because you are the last owner of the group. Please assign another member to the owner role first. + <tag>group</tag> + <usetemplate + name="okbutton" + yestext="OK"/> + </notification> + <notification icon="alert.tga" name="ConfirmKick"