Merge with viewer-chui

master
prep@lindenlab.com 2013-03-20 17:53:51 -05:00
commit f2948cb1eb
62 changed files with 1066 additions and 375 deletions

View File

@ -744,6 +744,7 @@ Marc Claridge
Marc2 Sands
Marianne McCann
Marine Kelley
CHUIBUG-134
STORM-281
MartinRJ Fayray
STORM-1844

View File

@ -598,6 +598,11 @@ S32 LLFontGL::maxDrawableChars(const llwchar* wchars, F32 max_pixels, S32 max_ch
if(!fgi)
{
fgi = mFontFreetype->getGlyphInfo(wch);
if (NULL == fgi)
{
return 0;
}
}
// account for glyphs that run beyond the starting point for the next glyphs

View File

@ -597,11 +597,6 @@ bool LLGLManager::initGL()
if (mGLVendor.substr(0,4) == "ATI ")
{
mGLVendorShort = "ATI";
//BOOL mobile = FALSE;
//if (mGLRenderer.find("MOBILITY") != std::string::npos)
//{
// mobile = TRUE;
//}
mIsATI = TRUE;
#if LL_WINDOWS && !LL_MESA_HEADLESS
@ -1489,9 +1484,7 @@ void assert_glerror()
void clear_glerror()
{
// Create or update texture to be used with this data
//GLenum error;
//error = glGetError();
glGetError();
glGetError();
}

View File

@ -169,6 +169,15 @@ BOOL LLChatEntry::handleSpecialKey(const KEY key, const MASK mask)
{
BOOL handled = FALSE;
// In the case of a chat entry, pressing RETURN when something is selected
// should NOT erase the selection (unlike a notecard, for example)
if (key == KEY_RETURN)
{
endOfDoc();
startSelection();
endSelection();
}
LLTextEditor::handleSpecialKey(key, mask);
switch(key)

View File

@ -1621,7 +1621,7 @@ void LLFloater::bringToFront( S32 x, S32 y )
// virtual
void LLFloater::setVisibleAndFrontmost(BOOL take_focus)
void LLFloater::setVisibleAndFrontmost(BOOL take_focus, const LLSD& key)
{
LLMultiFloater* hostp = getHost();
if (hostp)

View File

@ -305,7 +305,7 @@ public:
/*virtual*/ void handleVisibilityChange ( BOOL new_visibility ); // do not override
void setFrontmost(BOOL take_focus = TRUE);
virtual void setVisibleAndFrontmost(BOOL take_focus=TRUE);
virtual void setVisibleAndFrontmost(BOOL take_focus=TRUE, const LLSD& key = LLSD());
// Defaults to false.
virtual BOOL canSaveAs() const { return FALSE; }

View File

@ -488,12 +488,12 @@ void LLFloaterReg::toggleInstanceOrBringToFront(const LLSD& sdname, const LLSD&
{
host->setMinimized(FALSE);
instance->openFloater(key);
instance->setVisibleAndFrontmost();
instance->setVisibleAndFrontmost(true, key);
}
else if (!instance->getVisible())
{
instance->openFloater(key);
instance->setVisibleAndFrontmost();
instance->setVisibleAndFrontmost(true, key);
instance->setFocus(TRUE);
}
else
@ -506,16 +506,16 @@ void LLFloaterReg::toggleInstanceOrBringToFront(const LLSD& sdname, const LLSD&
if (instance->isMinimized())
{
instance->setMinimized(FALSE);
instance->setVisibleAndFrontmost();
instance->setVisibleAndFrontmost(true, key);
}
else if (!instance->isShown())
{
instance->openFloater(key);
instance->setVisibleAndFrontmost();
instance->setVisibleAndFrontmost(true, key);
}
else if (!instance->isFrontmost())
{
instance->setVisibleAndFrontmost();
instance->setVisibleAndFrontmost(true, key);
}
else
{

View File

@ -202,6 +202,14 @@ LLLineEditor::LLLineEditor(const LLLineEditor::Params& p)
LLLineEditor::~LLLineEditor()
{
mCommitOnFocusLost = FALSE;
// Make sure no context menu linger around once the widget is deleted
LLContextMenu* menu = static_cast<LLContextMenu*>(mContextMenuHandle.get());
if (menu)
{
menu->hide();
}
setContextMenu(NULL);
// calls onCommit() while LLLineEditor still valid
gFocusMgr.releaseFocusIfNeeded( this );

View File

@ -1483,16 +1483,22 @@ BOOL LLTabContainer::setTab(S32 which)
for(tuple_list_t::iterator iter = mTabList.begin(); iter != mTabList.end(); ++iter)
{
LLTabTuple* tuple = *iter;
if (!tuple)
continue;
BOOL is_selected = ( tuple == selected_tuple );
tuple->mButton->setUseEllipses(mUseTabEllipses);
tuple->mButton->setHAlign(mFontHalign);
tuple->mTabPanel->setVisible( is_selected );
// tuple->mTabPanel->setFocus(is_selected); // not clear that we want to do this here.
tuple->mButton->setToggleState( is_selected );
// RN: this limits tab-stops to active button only, which would require arrow keys to switch tabs
tuple->mButton->setTabStop( is_selected );
// Although the selected tab must be complete, we may have hollow LLTabTuple tucked in the list
if (tuple->mButton)
{
tuple->mButton->setUseEllipses(mUseTabEllipses);
tuple->mButton->setHAlign(mFontHalign);
tuple->mButton->setToggleState( is_selected );
// RN: this limits tab-stops to active button only, which would require arrow keys to switch tabs
tuple->mButton->setTabStop( is_selected );
}
if (tuple->mTabPanel)
{
tuple->mTabPanel->setVisible( is_selected );
//tuple->mTabPanel->setFocus(is_selected); // not clear that we want to do this here.
}
if (is_selected)
{
@ -1563,8 +1569,7 @@ BOOL LLTabContainer::selectTabByName(const std::string& name)
LLPanel* panel = getPanelByName(name);
if (!panel)
{
llwarns << "LLTabContainer::selectTabByName("
<< name << ") failed" << llendl;
llwarns << "LLTabContainer::selectTabByName(" << name << ") failed" << llendl;
return FALSE;
}

View File

@ -359,7 +359,6 @@ void LLTextBase::drawSelectionBackground()
S32 selection_left = llmin( mSelectionStart, mSelectionEnd );
S32 selection_right = llmax( mSelectionStart, mSelectionEnd );
LLRect selection_rect = mVisibleTextRect;
// Skip through the lines we aren't drawing.
LLRect content_display_rect = getVisibleDocumentRect();
@ -380,7 +379,7 @@ void LLTextBase::drawSelectionBackground()
S32 segment_offset;
getSegmentAndOffset(line_iter->mDocIndexStart, &segment_iter, &segment_offset);
//LLRect selection_rect;
LLRect selection_rect;
selection_rect.mLeft = line_iter->mRect.mLeft;
selection_rect.mRight = line_iter->mRect.mLeft;
selection_rect.mBottom = line_iter->mRect.mBottom;
@ -443,7 +442,7 @@ void LLTextBase::drawSelectionBackground()
rect_it != selection_rects.end();
++rect_it)
{
//LLRect selection_rect = *rect_it;
LLRect selection_rect = *rect_it;
selection_rect = *rect_it;
selection_rect.translate(mVisibleTextRect.mLeft - content_display_rect.mLeft, mVisibleTextRect.mBottom - content_display_rect.mBottom);
gl_rect_2d(selection_rect, selection_color);
@ -1087,7 +1086,14 @@ BOOL LLTextBase::handleRightMouseUp(S32 x, S32 y, MASK mask)
BOOL LLTextBase::handleDoubleClick(S32 x, S32 y, MASK mask)
{
mTripleClickTimer.setTimerExpirySec(TRIPLE_CLICK_INTERVAL);
//Don't start triple click timer if user have clicked on scrollbar
mVisibleTextRect = mScroller ? mScroller->getContentWindowRect() : getLocalRect();
if (x >= mVisibleTextRect.mLeft && x <= mVisibleTextRect.mRight
&& y >= mVisibleTextRect.mBottom && y <= mVisibleTextRect.mTop)
{
mTripleClickTimer.setTimerExpirySec(TRIPLE_CLICK_INTERVAL);
}
LLTextSegmentPtr cur_segment = getSegmentAtLocalPos(x, y);
if (cur_segment && cur_segment->handleDoubleClick(x, y, mask))
{
@ -1912,6 +1918,7 @@ void LLTextBase::createUrlContextMenu(S32 x, S32 y, const std::string &in_url)
registrar.add("Url.Execute", boost::bind(&LLUrlAction::executeSLURL, url));
registrar.add("Url.Teleport", boost::bind(&LLUrlAction::teleportToLocation, url));
registrar.add("Url.ShowProfile", boost::bind(&LLUrlAction::showProfile, url));
registrar.add("Url.AddFriend", boost::bind(&LLUrlAction::addFriend, url));
registrar.add("Url.ShowOnMap", boost::bind(&LLUrlAction::showLocationOnMap, url));
registrar.add("Url.CopyLabel", boost::bind(&LLUrlAction::copyLabelToClipboard, url));
registrar.add("Url.CopyUrl", boost::bind(&LLUrlAction::copyURLToClipboard, url));
@ -2330,7 +2337,6 @@ const LLWString& LLTextBase::getWText() const
S32 LLTextBase::getDocIndexFromLocalCoord( S32 local_x, S32 local_y, BOOL round, bool hit_past_end_of_line) const
{
// Figure out which line we're nearest to.
//LLRect visible_region = getVisibleDocumentRect();
LLRect doc_rect = mDocumentView->getRect();
S32 doc_y = local_y - doc_rect.mBottom;

View File

@ -24,7 +24,6 @@
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#include "linden_common.h"
#include "llurlaction.h"
@ -32,6 +31,7 @@
#include "llwindow.h"
#include "llurlregistry.h"
// global state for the callback functions
LLUrlAction::url_callback_t LLUrlAction::sOpenURLCallback;
LLUrlAction::url_callback_t LLUrlAction::sOpenURLInternalCallback;
@ -158,16 +158,33 @@ void LLUrlAction::showProfile(std::string url)
}
}
void LLUrlAction::sendIM(std::string url)
std::string LLUrlAction::getUserID(std::string url)
{
LLURI uri(url);
LLSD path_array = uri.pathArray();
std::string id_str;
if (path_array.size() == 4)
{
std::string id_str = path_array.get(2).asString();
if (LLUUID::validate(id_str))
{
executeSLURL("secondlife:///app/agent/" + id_str + "/im");
}
id_str = path_array.get(2).asString();
}
return id_str;
}
void LLUrlAction::sendIM(std::string url)
{
std::string id_str = getUserID(url);
if (LLUUID::validate(id_str))
{
executeSLURL("secondlife:///app/agent/" + id_str + "/im");
}
}
void LLUrlAction::addFriend(std::string url)
{
std::string id_str = getUserID(url);
if (LLUUID::validate(id_str))
{
executeSLURL("secondlife:///app/agent/" + id_str + "/requestfriend");
}
}

View File

@ -76,7 +76,9 @@ public:
/// if the Url specifies an SL command in the form like 'app/{cmd}/{id}/*', show its profile
static void showProfile(std::string url);
static std::string getUserID(std::string url);
static void sendIM(std::string url);
static void addFriend(std::string url);
/// specify the callbacks to enable this class's functionality
typedef boost::function<void (const std::string&)> url_callback_t;

View File

@ -1584,6 +1584,28 @@
<key>Value</key>
<integer>0</integer>
</map>
<key>ChatLoadGroupMaxMembers</key>
<map>
<key>Comment</key>
<string>Max number of active members we'll show up for an unresponsive group</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>S32</string>
<key>Value</key>
<real>100</real>
</map>
<key>ChatLoadGroupTimeout</key>
<map>
<key>Comment</key>
<string>Time we give the server to send group participants before we hit the server for group info (seconds)</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>F32</string>
<key>Value</key>
<real>10.0</real>
</map>
<key>ChatOnlineNotification</key>
<map>
<key>Comment</key>
@ -1694,17 +1716,6 @@
<key>Value</key>
<integer>131073</integer>
</map>
<key>NearbyChatIsNotTornOff</key>
<map>
<key>Comment</key>
<string>saving torn-off state of the nearby chat between sessions</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>1</integer>
</map>
<key>CloseChatOnReturn</key>
<map>
<key>Comment</key>
@ -4314,6 +4325,17 @@
<string>Boolean</string>
<key>Value</key>
<integer>1</integer>
</map>
<key>IMShowContentPanel</key>
<map>
<key>Comment</key>
<string>Show Toolbar and Body Panels</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>1</integer>
</map>
<key>IgnoreAllNotifications</key>
<map>

View File

@ -281,6 +281,17 @@
<key>Value</key>
<integer>2</integer>
</map>
<key>NearbyChatIsNotTornOff</key>
<map>
<key>Comment</key>
<string>saving torn-off state of the nearby chat between sessions</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>1</integer>
</map>
<key>ShowFavoritesOnLogin</key>
<map>
<key>Comment</key>

View File

@ -193,7 +193,7 @@ static void on_avatar_name_cache_start_im(const LLUUID& agent_id,
// static
void LLAvatarActions::startIM(const LLUUID& id)
{
if (id.isNull())
if (id.isNull() || gAgent.getID() == id)
return;
LLAvatarNameCache::get(id, boost::bind(&on_avatar_name_cache_start_im, _1, _2));

View File

@ -58,7 +58,7 @@
#include "llworld.h"
#include "lluiconstants.h"
#include "llstring.h"
#include "llurlaction.h"
#include "llviewercontrol.h"
static LLDefaultChildRegistry::Register<LLChatHistory> r("chat_history");
@ -156,6 +156,17 @@ public:
LLFloaterSidePanelContainer::showPanel("people", "panel_people",
LLSD().with("people_panel_tab_name", "blocked_panel").with("blocked_to_select", getAvatarId()));
}
else if (level == "map")
{
std::string url = "secondlife://" + mObjectData["slurl"].asString();
LLUrlAction::showLocationOnMap(url);
}
else if (level == "teleport")
{
std::string url = "secondlife://" + mObjectData["slurl"].asString();
LLUrlAction::teleportToLocation(url);
}
}
void onAvatarIconContextMenuItemClicked(const LLSD& userdata)
@ -820,6 +831,15 @@ void LLChatHistory::appendMessage(const LLChat& chat, const LLSD &args, const LL
body_message_params.font.style = "ITALIC";
}
if(chat.mChatType == CHAT_TYPE_WHISPER)
{
body_message_params.font.style = "ITALIC";
}
else if(chat.mChatType == CHAT_TYPE_SHOUT)
{
body_message_params.font.style = "BOLD";
}
bool message_from_log = chat.mChatStyle == CHAT_STYLE_HISTORY;
// We graying out chat history by graying out messages that contains full date in a time string
if (message_from_log)

View File

@ -427,14 +427,15 @@ LLChicletPanel::~LLChicletPanel()
void LLChicletPanel::onMessageCountChanged(const LLSD& data)
{
//LLUUID session_id = data["session_id"].asUUID();
//S32 unread = data["participant_unread"].asInteger();
// *TODO : we either suppress this method or return a value. Right now, it servers no purpose.
/*
//LLFloaterIMSession* im_floater = LLFloaterIMSession::findInstance(session_id);
//if (im_floater && im_floater->getVisible() && im_floater->hasFocus())
//{
// unread = 0;
//}
*/
}
void LLChicletPanel::objectChicletCallback(const LLSD& data)

View File

@ -28,9 +28,11 @@
#include "llagent.h"
#include "llavatarnamecache.h"
#include "llconversationlog.h"
#include "lldiriterator.h"
#include "llnotificationsutil.h"
#include "lltrans.h"
#include <boost/foreach.hpp>
#include "boost/lexical_cast.hpp"
const int CONVERSATION_LIFETIME = 30; // lifetime of LLConversation is 30 days by spec
@ -192,14 +194,17 @@ LLConversationLog::LLConversationLog() :
mAvatarNameCacheConnection(),
mLoggingEnabled(false)
{
LLControlVariable * keep_log_ctrlp = gSavedPerAccountSettings.getControl("KeepConversationLogTranscripts").get();
S32 log_mode = keep_log_ctrlp->getValue();
keep_log_ctrlp->getSignal()->connect(boost::bind(&LLConversationLog::enableLogging, this, _2));
if (log_mode > 0)
if(gSavedPerAccountSettings.controlExists("KeepConversationLogTranscripts"))
{
loadFromFile(getFileName());
LLControlVariable * keep_log_ctrlp = gSavedPerAccountSettings.getControl("KeepConversationLogTranscripts").get();
S32 log_mode = keep_log_ctrlp->getValue();
keep_log_ctrlp->getSignal()->connect(boost::bind(&LLConversationLog::enableLogging, this, _2));
if (log_mode > 0)
{
loadFromFile(getFileName());
enableLogging(log_mode);
enableLogging(log_mode);
}
}
}
@ -380,6 +385,36 @@ void LLConversationLog::cache()
}
}
void LLConversationLog::getListOfBackupLogs(std::vector<std::string>& list_of_backup_logs)
{
// get Users log directory
std::string dirname = gDirUtilp->getPerAccountChatLogsDir();
// add final OS dependent delimiter
dirname += gDirUtilp->getDirDelimiter();
// create search pattern
std::string pattern = "conversation.log.backup*";
LLDirIterator iter(dirname, pattern);
std::string filename;
while (iter.next(filename))
{
list_of_backup_logs.push_back(gDirUtilp->add(dirname, filename));
}
}
void LLConversationLog::deleteBackupLogs()
{
std::vector<std::string> backup_logs;
getListOfBackupLogs(backup_logs);
BOOST_FOREACH(const std::string& fullpath, backup_logs)
{
LLFile::remove(fullpath);
}
}
bool LLConversationLog::moveLog(const std::string &originDirectory, const std::string &targetDirectory)
{
@ -575,5 +610,6 @@ void LLConversationLog::onClearLogResponse(const LLSD& notification, const LLSD&
mConversations.clear();
notifyObservers();
cache();
deleteBackupLogs();
}
}

View File

@ -138,6 +138,8 @@ public:
*/
void cache();
bool moveLog(const std::string &originDirectory, const std::string &targetDirectory);
void getListOfBackupLogs(std::vector<std::string>& list_of_backup_logs);
void deleteBackupLogs();
void onClearLog();
void onClearLogResponse(const LLSD& notification, const LLSD& response);

View File

@ -198,6 +198,8 @@ void LLConversationLogList::refresh()
void LLConversationLogList::rebuildList()
{
const LLConversation * selected_conversationp = getSelectedConversation();
clear();
bool have_filter = !mNameFilter.empty();
@ -214,7 +216,12 @@ void LLConversationLogList::rebuildList()
addNewItem(&*iter);
}
// try to restore selection of item
if (NULL != selected_conversationp)
{
selectItemByUUID(selected_conversationp->getSessionID());
}
bool logging_enabled = log_instance.getIsLoggingEnabled();
bool log_empty = log_instance.isLogEmpty();
@ -238,8 +245,16 @@ void LLConversationLogList::rebuildList()
void LLConversationLogList::onCustomAction(const LLSD& userdata)
{
const LLConversation * selected_conversationp = getSelectedConversation();
if (NULL == selected_conversationp)
{
return;
}
const std::string command_name = userdata.asString();
const LLUUID& selected_id = getSelectedConversation()->getParticipantID();
const LLUUID& selected_conversation_participant_id = selected_conversationp->getParticipantID();
const LLUUID& selected_conversation_session_id = selected_conversationp->getSessionID();
LLIMModel::LLIMSession::SType stype = getSelectedSessionType();
if ("im" == command_name)
@ -247,11 +262,11 @@ void LLConversationLogList::onCustomAction(const LLSD& userdata)
switch (stype)
{
case LLIMModel::LLIMSession::P2P_SESSION:
LLAvatarActions::startIM(selected_id);
LLAvatarActions::startIM(selected_conversation_participant_id);
break;
case LLIMModel::LLIMSession::GROUP_SESSION:
LLGroupActions::startIM(getSelectedConversation()->getSessionID());
LLGroupActions::startIM(selected_conversation_session_id);
break;
default:
@ -263,11 +278,11 @@ void LLConversationLogList::onCustomAction(const LLSD& userdata)
switch (stype)
{
case LLIMModel::LLIMSession::P2P_SESSION:
LLAvatarActions::startCall(selected_id);
LLAvatarActions::startCall(selected_conversation_participant_id);
break;
case LLIMModel::LLIMSession::GROUP_SESSION:
LLGroupActions::startCall(getSelectedConversation()->getSessionID());
LLGroupActions::startCall(selected_conversation_session_id);
break;
default:
@ -279,11 +294,11 @@ void LLConversationLogList::onCustomAction(const LLSD& userdata)
switch (stype)
{
case LLIMModel::LLIMSession::P2P_SESSION:
LLAvatarActions::showProfile(selected_id);
LLAvatarActions::showProfile(selected_conversation_participant_id);
break;
case LLIMModel::LLIMSession::GROUP_SESSION:
LLGroupActions::show(getSelectedConversation()->getSessionID());
LLGroupActions::show(selected_conversation_session_id);
break;
default:
@ -292,52 +307,53 @@ void LLConversationLogList::onCustomAction(const LLSD& userdata)
}
else if ("chat_history" == command_name)
{
const LLUUID& session_id = getSelectedConversation()->getSessionID();
LLFloaterReg::showInstance("preview_conversation", session_id, true);
LLFloaterReg::showInstance("preview_conversation", selected_conversation_session_id, true);
}
else if ("offer_teleport" == command_name)
{
LLAvatarActions::offerTeleport(selected_id);
LLAvatarActions::offerTeleport(selected_conversation_participant_id);
}
else if("add_friend" == command_name)
{
if (!LLAvatarActions::isFriend(selected_id))
if (!LLAvatarActions::isFriend(selected_conversation_participant_id))
{
LLAvatarActions::requestFriendshipDialog(selected_id);
LLAvatarActions::requestFriendshipDialog(selected_conversation_participant_id);
}
}
else if("remove_friend" == command_name)
{
if (LLAvatarActions::isFriend(selected_id))
if (LLAvatarActions::isFriend(selected_conversation_participant_id))
{
LLAvatarActions::removeFriendDialog(selected_id);
LLAvatarActions::removeFriendDialog(selected_conversation_participant_id);
}
}
else if ("invite_to_group" == command_name)
{
LLAvatarActions::inviteToGroup(selected_id);
LLAvatarActions::inviteToGroup(selected_conversation_participant_id);
}
else if ("show_on_map" == command_name)
{
LLAvatarActions::showOnMap(selected_id);
LLAvatarActions::showOnMap(selected_conversation_participant_id);
}
else if ("share" == command_name)
{
LLAvatarActions::share(selected_id);
LLAvatarActions::share(selected_conversation_participant_id);
}
else if ("pay" == command_name)
{
LLAvatarActions::pay(selected_id);
LLAvatarActions::pay(selected_conversation_participant_id);
}
else if ("block" == command_name)
{
LLAvatarActions::toggleBlock(selected_id);
LLAvatarActions::toggleBlock(selected_conversation_participant_id);
}
}
bool LLConversationLogList::isActionEnabled(const LLSD& userdata)
{
if (numSelected() != 1)
const LLConversation * selected_conversationp = getSelectedConversation();
if (NULL == selected_conversationp || numSelected() > 1)
{
return false;
}
@ -345,7 +361,7 @@ bool LLConversationLogList::isActionEnabled(const LLSD& userdata)
const std::string command_name = userdata.asString();
LLIMModel::LLIMSession::SType stype = getSelectedSessionType();
const LLUUID& selected_id = getSelectedConversation()->getParticipantID();
const LLUUID& selected_id = selected_conversationp->getParticipantID();
bool is_p2p = LLIMModel::LLIMSession::P2P_SESSION == stype;
bool is_group = LLIMModel::LLIMSession::GROUP_SESSION == stype;
@ -374,7 +390,7 @@ bool LLConversationLogList::isActionEnabled(const LLSD& userdata)
{
return is_p2p && LLAvatarActions::canOfferTeleport(selected_id);
}
else if ("can_show_on_map")
else if ("can_show_on_map" == command_name)
{
return is_p2p && ((LLAvatarTracker::instance().isBuddyOnline(selected_id) && is_agent_mappable(selected_id)) || gAgent.isGodlike());
}
@ -384,9 +400,16 @@ bool LLConversationLogList::isActionEnabled(const LLSD& userdata)
bool LLConversationLogList::isActionChecked(const LLSD& userdata)
{
const LLConversation * selected_conversationp = getSelectedConversation();
if (NULL == selected_conversationp)
{
return false;
}
const std::string command_name = userdata.asString();
const LLUUID& selected_id = getSelectedConversation()->getParticipantID();
const LLUUID& selected_id = selected_conversationp->getParticipantID();
bool is_p2p = LLIMModel::LLIMSession::P2P_SESSION == getSelectedSessionType();
if ("is_blocked" == command_name)

View File

@ -139,6 +139,8 @@ void LLConversationItem::buildParticipantMenuOptions(menuentry_vec_t& items, U32
items.push_back(std::string("remove_friend"));
items.push_back(std::string("invite_to_group"));
items.push_back(std::string("separator_invite_to_group"));
if (static_cast<LLConversationItem*>(mParent)->getType() == CONV_SESSION_NEARBY)
items.push_back(std::string("zoom_in"));
items.push_back(std::string("map"));
items.push_back(std::string("share"));
items.push_back(std::string("pay"));

View File

@ -104,6 +104,15 @@ LLConversationViewSession::~LLConversationViewSession()
void LLConversationViewSession::setFlashState(bool flash_state)
{
if (flash_state && !mFlashStateOn)
{
// flash chat toolbar button if scrolled out of sight (because flashing will not be visible)
if (mContainer->isScrolledOutOfSight(this))
{
gToolBarView->flashCommand(LLCommandId("chat"), true);
}
}
mFlashStateOn = flash_state;
mFlashStarted = false;
mFlashTimer->stopFlashing();
@ -115,12 +124,6 @@ void LLConversationViewSession::startFlashing()
{
mFlashStarted = true;
mFlashTimer->startFlashing();
// flash chat toolbar button if scrolled out of sight (because flashing will not be visible)
if (mContainer->isScrolledOutOfSight(this))
{
gToolBarView->flashCommand(LLCommandId("chat"), true);
}
}
}
@ -254,20 +257,38 @@ BOOL LLConversationViewSession::handleMouseDown( S32 x, S32 y, MASK mask )
//This node (conversation) was selected and a child (participant) was not
if(result && getRoot())
{
if(getRoot()->getCurSelectedItem() == this)
{
LLConversationItem* item = dynamic_cast<LLConversationItem *>(getViewModelItem());
LLUUID session_id = item? item->getUUID() : LLUUID();
LLFloaterIMContainer *im_container = LLFloaterReg::getTypedInstance<LLFloaterIMContainer>("im_container");
im_container->flashConversationItemWidget(session_id,false);
im_container->selectConversationPair(session_id, false);
im_container->collapseMessagesPane(false);
}
selectConversationItem();
}
return result;
}
BOOL LLConversationViewSession::handleRightMouseDown( S32 x, S32 y, MASK mask )
{
BOOL result = LLFolderViewFolder::handleRightMouseDown(x, y, mask);
if(result)
{
selectConversationItem();
}
return result;
}
void LLConversationViewSession::selectConversationItem()
{
if(getRoot()->getCurSelectedItem() == this)
{
LLConversationItem* item = dynamic_cast<LLConversationItem *>(getViewModelItem());
LLUUID session_id = item? item->getUUID() : LLUUID();
LLFloaterIMContainer *im_container = LLFloaterReg::getTypedInstance<LLFloaterIMContainer>("im_container");
im_container->flashConversationItemWidget(session_id,false);
im_container->selectConversationPair(session_id, false);
im_container->collapseMessagesPane(false);
}
}
// virtual
S32 LLConversationViewSession::arrange(S32* width, S32* height)
{

View File

@ -68,6 +68,7 @@ public:
/*virtual*/ BOOL postBuild();
/*virtual*/ void draw();
/*virtual*/ BOOL handleMouseDown( S32 x, S32 y, MASK mask );
/*virtual*/ BOOL handleRightMouseDown( S32 x, S32 y, MASK mask );
/*virtual*/ S32 arrange(S32* width, S32* height);
@ -90,6 +91,7 @@ private:
void onCurrentVoiceSessionChanged(const LLUUID& session_id);
void startFlashing();
void selectConversationItem();
LLPanel* mItemPanel;
LLPanel* mCallIconLayoutPanel;

View File

@ -113,9 +113,11 @@ bool LLDelayedGestureError::doDialog(const LLErrorEntry &ent, bool uuid_ok)
}
}
LLNotificationsUtil::add(ent.mNotifyName, args);
if(!LLApp::isQuitting())
{
LLNotificationsUtil::add(ent.mNotifyName, args);
}
return true;
}

View File

@ -33,6 +33,7 @@
#include "lldir.h"
#include "llerror.h"
#include "llfloaterreg.h"
#include "llimview.h"
#include "llnotifications.h"
#include "llnotificationhandler.h"
#include "llnotificationstorage.h"
@ -145,6 +146,8 @@ void LLDoNotDisturbNotificationStorage::loadNotifications()
LLNotifications& instance = LLNotifications::instance();
bool imToastExists = false;
bool group_ad_hoc_toast_exists = false;
S32 toastSessionType;
bool offerExists = false;
for (LLSD::array_const_iterator notification_it = data.beginArray();
@ -158,7 +161,20 @@ void LLDoNotDisturbNotificationStorage::loadNotifications()
if(notificationName == toastName)
{
imToastExists = true;
toastSessionType = notification_params["payload"]["SESSION_TYPE"];
if(toastSessionType == LLIMModel::LLIMSession::P2P_SESSION)
{
imToastExists = true;
}
//Don't add group/ad-hoc messages to the notification system because
//this means the group/ad-hoc session has to be re-created
else if(toastSessionType == LLIMModel::LLIMSession::GROUP_SESSION
|| toastSessionType == LLIMModel::LLIMSession::ADHOC_SESSION)
{
//Just allows opening the conversation log for group/ad-hoc messages upon startup
group_ad_hoc_toast_exists = true;
continue;
}
}
else if(notificationName == offerName)
{
@ -197,7 +213,12 @@ void LLDoNotDisturbNotificationStorage::loadNotifications()
LLFloaterReg::showInstance("im_container");
}
if(imToastExists || offerExists)
if(group_ad_hoc_toast_exists)
{
LLFloaterReg::showInstance("conversation");
}
if(imToastExists || group_ad_hoc_toast_exists || offerExists)
{
make_ui_sound_deferred("UISndNewIncomingIMSession");
}

View File

@ -53,6 +53,7 @@
#include "llcallbacklist.h"
#include "llworld.h"
#include "llsdserialize.h"
#include "llviewerobjectlist.h"
//
// LLFloaterIMContainer
@ -62,8 +63,7 @@ LLFloaterIMContainer::LLFloaterIMContainer(const LLSD& seed, const Params& param
mExpandCollapseBtn(NULL),
mConversationsRoot(NULL),
mConversationsEventStream("ConversationsEvents"),
mInitialized(false),
mIsFirstLaunch(false)
mInitialized(false)
{
mEnableCallbackRegistrar.add("IMFloaterContainer.Check", boost::bind(&LLFloaterIMContainer::isActionChecked, this, _2));
mCommitCallbackRegistrar.add("IMFloaterContainer.Action", boost::bind(&LLFloaterIMContainer::onCustomAction, this, _2));
@ -114,6 +114,7 @@ void LLFloaterIMContainer::sessionAdded(const LLUUID& session_id, const std::str
void LLFloaterIMContainer::sessionActivated(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id)
{
selectConversationPair(session_id, true);
collapseMessagesPane(false);
}
void LLFloaterIMContainer::sessionVoiceOrIMStarted(const LLUUID& session_id)
@ -225,10 +226,11 @@ BOOL LLFloaterIMContainer::postBuild()
childSetAction("add_btn", boost::bind(&LLFloaterIMContainer::onAddButtonClicked, this));
collapseMessagesPane(gSavedPerAccountSettings.getBOOL("ConversationsMessagePaneCollapsed"));
collapseConversationsPane(gSavedPerAccountSettings.getBOOL("ConversationsListPaneCollapsed"));
collapseConversationsPane(gSavedPerAccountSettings.getBOOL("ConversationsListPaneCollapsed"), false);
LLAvatarNameCache::addUseDisplayNamesCallback(boost::bind(&LLFloaterIMSessionTab::processChatHistoryStyleUpdate, false));
mMicroChangedSignal = LLVoiceClient::getInstance()->MicroChangedCallback(boost::bind(&LLFloaterIMContainer::updateSpeakBtnState, this));
if (! mMessagesPane->isCollapsed())
if (! mMessagesPane->isCollapsed() && ! mConversationsPane->isCollapsed())
{
S32 conversations_panel_width = gSavedPerAccountSettings.getS32("ConversationsListPaneWidth");
LLRect conversations_panel_rect = mConversationsPane->getRect();
@ -243,7 +245,6 @@ BOOL LLFloaterIMContainer::postBuild()
mGeneralTitle = getTitle();
mInitialized = true;
mIsFirstLaunch = true;
// Add callbacks:
// We'll take care of view updates on idle
@ -278,12 +279,6 @@ void LLFloaterIMContainer::addFloater(LLFloater* floaterp,
LLUUID session_id = floaterp->getKey();
// Make sure the message panel is open when adding a floater or it stays mysteriously hidden
if (!mIsFirstLaunch)
{
collapseMessagesPane(false);
}
// Add the floater
LLMultiFloater::addFloater(floaterp, select_added_floater, insertion_point);
@ -644,8 +639,6 @@ void LLFloaterIMContainer::collapseMessagesPane(bool collapse)
return;
}
mIsFirstLaunch = false;
// Save current width of panels before collapsing/expanding right pane.
S32 conv_pane_width = mConversationsPane->getRect().getWidth();
S32 msg_pane_width = mMessagesPane->getRect().getWidth();
@ -667,7 +660,7 @@ void LLFloaterIMContainer::collapseMessagesPane(bool collapse)
// Make sure layout is updated before resizing conversation pane.
mConversationsStack->updateLayout();
updateState(collapse, gSavedPerAccountSettings.getS32("ConversationsMessagePaneWidth"));
reshapeFloaterAndSetResizeLimits(collapse, gSavedPerAccountSettings.getS32("ConversationsMessagePaneWidth"));
if (!collapse)
{
@ -676,7 +669,7 @@ void LLFloaterIMContainer::collapseMessagesPane(bool collapse)
}
}
void LLFloaterIMContainer::collapseConversationsPane(bool collapse)
void LLFloaterIMContainer::collapseConversationsPane(bool collapse, bool save_is_allowed /*=true*/)
{
if (mConversationsPane->isCollapsed() == collapse)
{
@ -690,7 +683,7 @@ void LLFloaterIMContainer::collapseConversationsPane(bool collapse)
// Save current width of Conversation panel before collapsing/expanding right pane.
S32 conv_pane_width = mConversationsPane->getRect().getWidth();
if (collapse)
if (collapse && save_is_allowed)
{
// Save the conversations pane width before collapsing it.
gSavedPerAccountSettings.setS32("ConversationsListPaneWidth", conv_pane_width);
@ -700,10 +693,18 @@ void LLFloaterIMContainer::collapseConversationsPane(bool collapse)
}
mConversationsStack->collapsePanel(mConversationsPane, collapse);
if (!collapse)
{
// Make sure layout is updated before resizing conversation pane.
mConversationsStack->updateLayout();
// Restore conversation's pane previous width.
mConversationsPane->setTargetDim(gSavedPerAccountSettings.getS32("ConversationsListPaneWidth"));
}
S32 delta_width = gSavedPerAccountSettings.getS32("ConversationsListPaneWidth") - mConversationsPane->getMinDim();
S32 delta_width =
gSavedPerAccountSettings.getS32("ConversationsListPaneWidth") - mConversationsPane->getMinDim();
updateState(collapse, delta_width);
reshapeFloaterAndSetResizeLimits(collapse, delta_width);
for (conversations_widgets_map::iterator widget_it = mConversationsWidgets.begin();
widget_it != mConversationsWidgets.end(); ++widget_it)
@ -723,21 +724,20 @@ void LLFloaterIMContainer::collapseConversationsPane(bool collapse)
}
}
void LLFloaterIMContainer::updateState(bool collapse, S32 delta_width)
void LLFloaterIMContainer::reshapeFloaterAndSetResizeLimits(bool collapse, S32 delta_width)
{
LLRect floater_rect = getRect();
floater_rect.mRight += ((collapse ? -1 : 1) * delta_width);
// Set by_user = true so that reshaped rect is saved in user_settings.
setShape(floater_rect, true);
updateResizeLimits();
bool is_left_pane_expanded = !mConversationsPane->isCollapsed();
bool is_right_pane_expanded = !mMessagesPane->isCollapsed();
bool at_least_one_panel_is_expanded =
! (mConversationsPane->isCollapsed() && mMessagesPane->isCollapsed());
setCanResize(is_left_pane_expanded || is_right_pane_expanded);
setCanMinimize(is_left_pane_expanded || is_right_pane_expanded);
setCanResize(at_least_one_panel_is_expanded);
setCanMinimize(at_least_one_panel_is_expanded);
assignResizeLimits();
@ -766,15 +766,9 @@ void LLFloaterIMContainer::assignResizeLimits()
S32 msg_pane_min_width = is_msg_pane_expanded ? mMessagesPane->getExpandedMinDim() : 0;
S32 new_min_width = conv_pane_target_width + msg_pane_min_width + summary_width_of_visible_borders;
if (is_conv_pane_expanded)
{
// Save the conversations pane width.
gSavedPerAccountSettings.setS32(
"ConversationsListPaneWidth",
mConversationsPane->getRect().getWidth());
}
setResizeLimits(new_min_width, getMinHeight());
mConversationsStack->updateLayout();
}
void LLFloaterIMContainer::onAddButtonClicked()
@ -1033,6 +1027,10 @@ void LLFloaterIMContainer::doToParticipants(const std::string& command, uuid_vec
{
LLAvatarActions::inviteToGroup(userID);
}
else if ("zoom_in" == command)
{
handle_zoom_to_object(userID);
}
else if ("map" == command)
{
LLAvatarActions::showOnMap(userID);
@ -1254,6 +1252,10 @@ bool LLFloaterIMContainer::enableContextMenuItem(const std::string& item, uuid_v
{
return LLAvatarActions::canCall();
}
else if ("can_zoom_in" == item)
{
return is_single_select && gObjectList.findObject(single_id);
}
else if ("can_show_on_map" == item)
{
return (is_single_select ? (LLAvatarTracker::instance().isBuddyOnline(single_id) && is_agent_mappable(single_id)) || gAgent.isGodlike() : false);
@ -1327,6 +1329,9 @@ void LLFloaterIMContainer::showConversation(const LLUUID& session_id)
{
setVisibleAndFrontmost(false);
selectConversationPair(session_id, true);
LLFloaterIMSessionTab* session_floater = LLFloaterIMSessionTab::findConversation(session_id);
session_floater->restoreFloater();
}
void LLFloaterIMContainer::clearAllFlashStates()
@ -1402,6 +1407,10 @@ BOOL LLFloaterIMContainer::selectConversationPair(const LLUUID& session_id, bool
// Switch to the conversation floater that is being selected
selectFloater(session_floater);
}
else
{
showStub(true);
}
}
// Set the focus on the selected floater
@ -1412,7 +1421,7 @@ BOOL LLFloaterIMContainer::selectConversationPair(const LLUUID& session_id, bool
session_floater->setMinimized(is_minimized);
}
}
flashConversationItemWidget(session_id,false);
return handled;
}
@ -1880,6 +1889,9 @@ bool LLFloaterIMContainer::isScrolledOutOfSight(LLConversationViewSession* conve
{
llassert(conversation_item_widget != NULL);
// make sure the widget is actually in the right spot first
mConversationsRoot->arrange(NULL, NULL);
// check whether the widget is in the visible portion of the scroll container
LLRect widget_rect;
conversation_item_widget->localRectToOtherView(conversation_item_widget->getLocalRect(), &widget_rect, mConversationsRoot);
@ -1907,7 +1919,19 @@ BOOL LLFloaterIMContainer::handleKeyHere(KEY key, MASK mask )
return TRUE;
}
bool LLFloaterIMContainer::selectNextorPreviousConversation(bool select_next)
bool LLFloaterIMContainer::selectAdjacentConversation(bool focus_selected)
{
bool selectedAdjacentConversation = selectNextorPreviousConversation(true, focus_selected);
if(!selectedAdjacentConversation)
{
selectedAdjacentConversation = selectNextorPreviousConversation(false, focus_selected);
}
return selectedAdjacentConversation;
}
bool LLFloaterIMContainer::selectNextorPreviousConversation(bool select_next, bool focus_selected)
{
if (mConversationsWidgets.size() > 1)
{
@ -1928,12 +1952,7 @@ bool LLFloaterIMContainer::selectNextorPreviousConversation(bool select_next)
LLConversationItem* vmi = dynamic_cast<LLConversationItem*>(new_selection->getViewModelItem());
if (vmi)
{
selectConversationPair(vmi->getUUID(), true);
LLFloater* floaterp = get_ptr_in_map(mSessions, getSelectedSession());
if(floaterp && !floaterp->isTornOff())
{
setFocus(TRUE);
}
selectConversationPair(vmi->getUUID(), true, focus_selected);
return true;
}
}
@ -1957,11 +1976,6 @@ void LLFloaterIMContainer::closeFloater(bool app_quitting/* = false*/)
// Most of the time the user will never see this state.
setMinimized(FALSE);
// Save the conversations pane width.
gSavedPerAccountSettings.setS32(
"ConversationsListPaneWidth",
mConversationsPane->getRect().getWidth());
LLFloater::closeFloater(app_quitting);
}

View File

@ -72,7 +72,8 @@ public:
void selectNextConversationByID(const LLUUID& session_id);
BOOL selectConversationPair(const LLUUID& session_id, bool select_widget, bool focus_floater = true);
void clearAllFlashStates();
bool selectNextorPreviousConversation(bool select_next);
bool selectAdjacentConversation(bool focus_selected);
bool selectNextorPreviousConversation(bool select_next, bool focus_selected = true);
void expandConversation();
/*virtual*/ void tabClose();
@ -128,9 +129,9 @@ private:
void processParticipantsStyleUpdate();
void onSpeakButtonClicked();
void collapseConversationsPane(bool collapse);
void collapseConversationsPane(bool collapse, bool save_is_allowed=true);
void updateState(bool collapse, S32 delta_width);
void reshapeFloaterAndSetResizeLimits(bool collapse, S32 delta_width);
void onAddButtonClicked();
void onAvatarPicked(const uuid_vec_t& ids);
@ -173,7 +174,6 @@ private:
LLLayoutStack* mConversationsStack;
bool mInitialized;
bool mIsFirstLaunch;
LLUUID mSelectedSession;
std::string mGeneralTitle;

View File

@ -257,14 +257,25 @@ void LLFloaterIMNearbyChat::setVisible(BOOL visible)
}
}
void LLFloaterIMNearbyChat::setVisibleAndFrontmost(BOOL take_focus, const LLSD& key)
{
LLFloaterIMSessionTab::setVisibleAndFrontmost(take_focus, key);
if(!isTornOff() && matchesKey(key))
{
LLFloaterIMContainer::getInstance()->selectConversationPair(mSessionID, true, false);
}
}
// virtual
void LLFloaterIMNearbyChat::onTearOffClicked()
{
LLFloaterIMSessionTab::onTearOffClicked();
// see CHUI-170: Save torn-off state of the nearby chat between sessions
BOOL in_the_multifloater = !isTornOff();
gSavedSettings.setBOOL("NearbyChatIsNotTornOff", in_the_multifloater);
BOOL in_the_multifloater = (BOOL)getHost();
gSavedPerAccountSettings.setBOOL("NearbyChatIsNotTornOff", in_the_multifloater);
}
@ -279,6 +290,7 @@ void LLFloaterIMNearbyChat::onOpen(const LLSD& key)
void LLFloaterIMNearbyChat::onClose(bool app_quitting)
{
// Override LLFloaterIMSessionTab::onClose() so that Nearby Chat is not removed from the conversation floater
LLFloaterIMSessionTab::restoreFloater();
onClickCloseBtn();
}
@ -286,8 +298,10 @@ void LLFloaterIMNearbyChat::onClose(bool app_quitting)
void LLFloaterIMNearbyChat::onClickCloseBtn()
{
if (!isTornOff())
{
return;
onTearOffClicked();
}
LLFloaterIMSessionTab::onTearOffClicked();
LLFloaterIMContainer *im_box = LLFloaterIMContainer::findInstance();
if (im_box)
@ -323,7 +337,7 @@ bool LLFloaterIMNearbyChat::isChatVisible() const
if (im_box != NULL)
{
isVisible =
isChatMultiTab() && gSavedSettings.getBOOL("NearbyChatIsNotTornOff")?
isChatMultiTab() && gSavedPerAccountSettings.getBOOL("NearbyChatIsNotTornOff")?
im_box->getVisible() && !im_box->isMinimized() :
getVisible() && !isMinimized();
}
@ -334,6 +348,11 @@ bool LLFloaterIMNearbyChat::isChatVisible() const
void LLFloaterIMNearbyChat::showHistory()
{
openFloater();
if(!isMessagePaneExpanded())
{
restoreFloater();
setFocus(true);
}
setResizeLimits(getMinWidth(), EXPANDED_MIN_HEIGHT);
}
@ -406,6 +425,12 @@ BOOL LLFloaterIMNearbyChat::matchChatTypeTrigger(const std::string& in_str, std:
void LLFloaterIMNearbyChat::onChatBoxKeystroke()
{
LLFloaterIMContainer* im_box = LLFloaterIMContainer::findInstance();
if (im_box)
{
im_box->flashConversationItemWidget(mSessionID,false);
}
LLFirstUse::otherAvatarChatFirst(false);
LLWString raw_text = mInputEditor->getWText();
@ -714,7 +739,14 @@ void LLFloaterIMNearbyChat::startChat(const char* line)
LLFloaterIMNearbyChat* nearby_chat = LLFloaterReg::getTypedInstance<LLFloaterIMNearbyChat>("nearby_chat");
if (nearby_chat)
{
nearby_chat->show();
if(!nearby_chat->isTornOff())
{
nearby_chat->show();
}
if(nearby_chat->isMinimized())
{
nearby_chat->setMinimized(false);
}
nearby_chat->setVisible(TRUE);
nearby_chat->setFocus(TRUE);
nearby_chat->mInputEditor->setFocus(TRUE);

View File

@ -54,6 +54,7 @@ public:
/*virtual*/ void onOpen(const LLSD& key);
/*virtual*/ void onClose(bool app_quitting);
/*virtual*/ void setVisible(BOOL visible);
/*virtual*/ void setVisibleAndFrontmost(BOOL take_focus=TRUE, const LLSD& key = LLSD());
/*virtual*/ void closeHostedFloater();
void loadHistory();

View File

@ -559,12 +559,14 @@ void LLFloaterIMNearbyChatHandler::processChat(const LLChat& chat_msg,
LLFloaterIMContainer* im_box = LLFloaterReg::getTypedInstance<LLFloaterIMContainer>("im_container");
if( nearby_chat->hasFocus()
if(( nearby_chat->hasFocus()
|| im_box->hasFocus()
|| ( chat_msg.mSourceType == CHAT_SOURCE_AGENT
&& gSavedSettings.getBOOL("UseChatBubbles") )
|| mChannel.isDead()
|| !mChannel.get()->getShowToasts() ) // to prevent toasts in Do Not Disturb mode
|| !mChannel.get()->getShowToasts() )
&& nearby_chat->isMessagePaneExpanded())
// to prevent toasts in Do Not Disturb mode
return;//no need in toast if chat is visible or if bubble chat is enabled
// arrange a channel on a screen
@ -606,7 +608,7 @@ void LLFloaterIMNearbyChatHandler::processChat(const LLChat& chat_msg,
//Don't show nearby toast, if conversation is visible but not focused
LLFloaterIMSessionTab* session_floater = LLFloaterIMSessionTab::getConversation(LLUUID());
if (session_floater
if (session_floater && session_floater->isMessagePaneExpanded()
&& session_floater->isInVisibleChain() && !session_floater->isMinimized()
&& !(session_floater->getHost() && session_floater->getHost()->isMinimized()))
{
@ -614,7 +616,7 @@ void LLFloaterIMNearbyChatHandler::processChat(const LLChat& chat_msg,
}
//Will show toast when chat preference is set
if(gSavedSettings.getString("NotificationNearbyChatOptions") == "toast")
if((gSavedSettings.getString("NotificationNearbyChatOptions") == "toast") || !session_floater->isMessagePaneExpanded())
{
// Add a nearby chat toast.
LLUUID id;

View File

@ -618,7 +618,7 @@ void LLFloaterIMSession::onClose(bool app_quitting)
// Last change:
// EXT-3516 X Button should end IM session, _ button should hide
gIMMgr->leaveSession(mSessionID);
LLFloaterIMSessionTab::restoreFloater();
// Clean up the conversation *after* the session has been ended
LLFloaterIMSessionTab::onClose(app_quitting);
}
@ -892,6 +892,11 @@ void LLFloaterIMSession::onInputEditorFocusLost(LLFocusableElement* caller, void
void LLFloaterIMSession::onInputEditorKeystroke(LLTextEditor* caller, void* userdata)
{
LLFloaterIMSession* self = (LLFloaterIMSession*)userdata;
LLFloaterIMContainer* im_box = LLFloaterIMContainer::findInstance();
if (im_box)
{
im_box->flashConversationItemWidget(self->mSessionID,false);
}
std::string text = self->mInputEditor->getText();
// Deleting all text counts as stopping typing.

View File

@ -61,6 +61,7 @@ LLFloaterIMSessionTab::LLFloaterIMSessionTab(const LLSD& session_id)
, mRefreshTimer(new LLTimer())
, mIsHostAttached(false)
, mHasVisibleBeenInitialized(false)
, mIsParticipantListExpanded(true)
{
setAutoFocus(FALSE);
mSession = LLIMModel::getInstance()->findIMSession(mSessionID);
@ -169,7 +170,7 @@ void LLFloaterIMSessionTab::addToHost(const LLUUID& session_id)
conversp->setHostAttached(true);
if (!conversp->isNearbyChat()
|| gSavedSettings.getBOOL("NearbyChatIsNotTornOff"))
|| gSavedPerAccountSettings.getBOOL("NearbyChatIsNotTornOff"))
{
floater_container->addFloater(conversp, false, LLTabContainer::RIGHT_OF_CURRENT);
}
@ -180,6 +181,7 @@ void LLFloaterIMSessionTab::addToHost(const LLUUID& session_id)
// LLFloater::mLastHostHandle = floater_container (a "future" host)
conversp->setHost(floater_container);
conversp->setHost(NULL);
conversp->forceReshape();
}
// Added floaters share some state (like sort order) with their host
@ -192,19 +194,28 @@ BOOL LLFloaterIMSessionTab::postBuild()
{
BOOL result;
mBodyStack = getChild<LLLayoutStack>("main_stack");
mCloseBtn = getChild<LLButton>("close_btn");
mCloseBtn->setCommitCallback(boost::bind(&LLFloater::onClickClose, this));
mExpandCollapseBtn = getChild<LLButton>("expand_collapse_btn");
mExpandCollapseBtn->setClickedCallback(boost::bind(&LLFloaterIMSessionTab::onSlide, this));
mExpandCollapseLineBtn = getChild<LLButton>("minz_btn");
mExpandCollapseLineBtn->setClickedCallback(boost::bind(&LLFloaterIMSessionTab::onCollapseToLine, this));
mTearOffBtn = getChild<LLButton>("tear_off_btn");
mTearOffBtn->setCommitCallback(boost::bind(&LLFloaterIMSessionTab::onTearOffClicked, this));
mGearBtn = getChild<LLButton>("gear_btn");
mParticipantListPanel = getChild<LLLayoutPanel>("speakers_list_panel");
mToolbarPanel = getChild<LLLayoutPanel>("toolbar_panel");
mContentPanel = getChild<LLLayoutPanel>("body_panel");
mInputButtonPanel = getChild<LLLayoutPanel>("input_button_layout_panel");
mInputButtonPanel->setVisible(false);
// Add a scroller for the folder (participant) view
LLRect scroller_view_rect = mParticipantListPanel->getRect();
scroller_view_rect.translate(-scroller_view_rect.mLeft, -scroller_view_rect.mBottom);
@ -231,7 +242,7 @@ BOOL LLFloaterIMSessionTab::postBuild()
setOpenPositioning(LLFloaterEnums::POSITIONING_RELATIVE);
mSaveRect = isNearbyChat()
&& !gSavedSettings.getBOOL("NearbyChatIsNotTornOff");
&& !gSavedPerAccountSettings.getBOOL("NearbyChatIsNotTornOff");
initRectControl();
if (isChatMultiTab())
@ -253,6 +264,7 @@ BOOL LLFloaterIMSessionTab::postBuild()
p.root = NULL;
p.use_ellipses = true;
p.options_menu = "menu_conversation.xml";
p.name = "root";
mConversationsRoot = LLUICtrlFactory::create<LLFolderView>(p);
mConversationsRoot->setCallbackRegistrar(&mCommitCallbackRegistrar);
// Attach that root to the scroller
@ -261,6 +273,8 @@ BOOL LLFloaterIMSessionTab::postBuild()
mConversationsRoot->setFollowsAll();
mConversationsRoot->addChild(mConversationsRoot->mStatusTextBox);
setMessagePaneExpanded(true);
buildConversationViewParticipant();
refreshConversation();
@ -268,6 +282,12 @@ BOOL LLFloaterIMSessionTab::postBuild()
mRefreshTimer->setTimerExpirySec(0);
mRefreshTimer->start();
initBtns();
if (mIsParticipantListExpanded != (bool)gSavedSettings.getBOOL("IMShowControlPanel"))
{
LLFloaterIMSessionTab::onSlide(this);
}
return result;
}
@ -324,13 +344,6 @@ void LLFloaterIMSessionTab::onFocusReceived()
}
LLTransientDockableFloater::onFocusReceived();
LLFloaterIMContainer* container = LLFloaterReg::findTypedInstance<LLFloaterIMContainer>("im_container");
if (container)
{
container->selectConversationPair(mSessionID, true);
container->showStub(! getHost());
}
}
void LLFloaterIMSessionTab::onFocusLost()
@ -644,11 +657,12 @@ void LLFloaterIMSessionTab::updateHeaderAndToolbar()
// Participant list should be visible only in torn off floaters.
bool is_participant_list_visible =
!is_not_torn_off
&& gSavedSettings.getBOOL("IMShowControlPanel")
&& mIsParticipantListExpanded
&& !mIsP2PChat;
mParticipantListPanel->setVisible(is_participant_list_visible);
// Display collapse image (<<) if the floater is hosted
// or if it is torn off but has an open control panel.
bool is_expanded = is_not_torn_off || is_participant_list_visible;
@ -672,6 +686,7 @@ void LLFloaterIMSessionTab::updateHeaderAndToolbar()
mTearOffBtn->setImageOverlay(getString(is_not_torn_off? "tear_off_icon" : "return_icon"));
mTearOffBtn->setToolTip(getString(is_not_torn_off? "tooltip_to_separate_window" : "tooltip_to_main_window"));
mCloseBtn->setVisible(is_not_torn_off && !mIsNearbyChat);
enableDisableCallBtn();
@ -775,14 +790,70 @@ void LLFloaterIMSessionTab::onSlide(LLFloaterIMSessionTab* self)
// Expand/collapse the IM control panel
self->mParticipantListPanel->setVisible(expand);
gSavedSettings.setBOOL("IMShowControlPanel", expand);
gSavedSettings.setBOOL("IMShowControlPanel", expand);
self->mIsParticipantListExpanded = expand;
self->mExpandCollapseBtn->setImageOverlay(self->getString(expand ? "collapse_icon" : "expand_icon"));
}
}
}
void LLFloaterIMSessionTab::onCollapseToLine(LLFloaterIMSessionTab* self)
{
LLFloaterIMContainer* host_floater = dynamic_cast<LLFloaterIMContainer*>(self->getHost());
if (!host_floater)
{
bool expand = self->isMessagePaneExpanded();
self->mExpandCollapseLineBtn->setImageOverlay(self->getString(expand ? "collapseline_icon" : "expandline_icon"));
self->mContentPanel->setVisible(!expand);
self->mToolbarPanel->setVisible(!expand);
self->reshapeFloater(expand);
self->setMessagePaneExpanded(!expand);
}
}
void LLFloaterIMSessionTab::reshapeFloater(bool collapse)
{
LLRect floater_rect = getRect();
if(collapse)
{
mFloaterHeight = floater_rect.getHeight();
S32 height = mContentPanel->getRect().getHeight() + mToolbarPanel->getRect().getHeight();
floater_rect.mTop -= height;
enableResizeCtrls(true, true, false);
}
else
{
floater_rect.mTop = floater_rect.mBottom + mFloaterHeight;
enableResizeCtrls(true, true, true);
}
setShape(floater_rect, true);
mBodyStack->updateLayout();
}
void LLFloaterIMSessionTab::restoreFloater()
{
if(!isMessagePaneExpanded())
{
if(isMinimized())
{
setMinimized(false);
}
mContentPanel->setVisible(true);
mToolbarPanel->setVisible(true);
LLRect floater_rect = getRect();
floater_rect.mTop = floater_rect.mBottom + mFloaterHeight;
setShape(floater_rect, true);
mBodyStack->updateLayout();
mExpandCollapseLineBtn->setImageOverlay(getString("expandline_icon"));
setMessagePaneExpanded(true);
enableResizeCtrls(true, true, true);
}
}
/*virtual*/
void LLFloaterIMSessionTab::onOpen(const LLSD& key)
{
@ -792,19 +863,33 @@ void LLFloaterIMSessionTab::onOpen(const LLSD& key)
// Show the messages pane when opening a floater hosted in the Conversations
host_floater->collapseMessagesPane(false);
}
mInputButtonPanel->setVisible(isTornOff());
}
void LLFloaterIMSessionTab::onTearOffClicked()
{
setFollows(isTornOff()? FOLLOWS_ALL : FOLLOWS_NONE);
restoreFloater();
setFollows(isTornOff()? FOLLOWS_ALL : FOLLOWS_NONE);
mSaveRect = isTornOff();
initRectControl();
LLFloater::onClickTearOff(this);
LLFloaterIMContainer* container = LLFloaterReg::findTypedInstance<LLFloaterIMContainer>("im_container");
if (isTornOff())
{
container->selectAdjacentConversation(false);
forceReshape();
}
//Upon re-docking the torn off floater, select the corresponding conversation line item
else
{
container->selectConversation(mSessionID);
}
mInputButtonPanel->setVisible(isTornOff());
refreshConversation();
updateGearBtn();
}

View File

@ -98,6 +98,9 @@ public:
LLConversationItem* getCurSelectedViewModelItem();
void forceReshape();
virtual BOOL handleKeyHere( KEY key, MASK mask );
bool isMessagePaneExpanded(){return mMessagePaneExpanded;}
void setMessagePaneExpanded(bool expanded){mMessagePaneExpanded = expanded;}
void restoreFloater();
protected:
@ -111,6 +114,8 @@ protected:
bool onIMShowModesMenuItemCheck(const LLSD& userdata);
bool onIMShowModesMenuItemEnable(const LLSD& userdata);
static void onSlide(LLFloaterIMSessionTab *self);
static void onCollapseToLine(LLFloaterIMSessionTab *self);
void reshapeFloater(bool collapse);
// refresh a visual state of the Call button
void updateCallBtnState(bool callIsActive);
@ -139,13 +144,21 @@ protected:
bool mIsNearbyChat;
bool mIsP2PChat;
bool mMessagePaneExpanded;
bool mIsParticipantListExpanded;
LLIMModel::LLIMSession* mSession;
// Participants list: model and view
LLConversationViewParticipant* createConversationViewParticipant(LLConversationItem* item);
LLUUID mSessionID;
LLLayoutStack* mBodyStack;
LLLayoutPanel* mParticipantListPanel; // add the widgets to that see mConversationsListPanel
LLLayoutPanel* mContentPanel;
LLLayoutPanel* mToolbarPanel;
LLLayoutPanel* mInputButtonPanel;
LLParticipantList* getParticipantList();
conversations_widgets_map mConversationsWidgets;
LLConversationViewModel mConversationViewModel;
@ -157,11 +170,14 @@ protected:
LLChatEntry* mInputEditor;
int mInputEditorTopPad; // padding between input field and chat history
LLButton* mExpandCollapseLineBtn;
LLButton* mExpandCollapseBtn;
LLButton* mTearOffBtn;
LLButton* mCloseBtn;
LLButton* mGearBtn;
S32 mFloaterHeight;
private:
// Handling selection and contextual menu

View File

@ -443,6 +443,8 @@ BOOL LLFloaterPreference::postBuild()
std::string cache_location = gDirUtilp->getExpandedFilename(LL_PATH_CACHE, "");
setCacheLocation(cache_location);
getChild<LLUICtrl>("log_path_string")->setEnabled(FALSE); // make it read-only but selectable
getChild<LLComboBox>("language_combobox")->setCommitCallback(boost::bind(&LLFloaterPreference::onLanguageChange, this));
getChild<LLComboBox>("FriendIMOptions")->setCommitCallback(boost::bind(&LLFloaterPreference::onNotificationsChange, this,"FriendIMOptions"));
@ -1572,7 +1574,6 @@ void LLFloaterPreference::setPersonalInfo(const std::string& visibility, bool im
getChildView("send_im_to_email")->setEnabled(TRUE);
getChild<LLUICtrl>("send_im_to_email")->setValue(im_via_email);
getChildView("favorites_on_login_check")->setEnabled(TRUE);
getChildView("log_path_string")->setEnabled(FALSE);// LineEditor becomes readonly in this case.
getChildView("log_path_button")->setEnabled(TRUE);
getChildView("chat_font_size")->setEnabled(TRUE);
}
@ -1667,7 +1668,10 @@ void LLFloaterPreference::onClickActionChange()
void LLFloaterPreference::onDeleteTranscripts()
{
LLNotificationsUtil::add("PreferenceChatDeleteTranscripts", LLSD(), LLSD(), boost::bind(&LLFloaterPreference::onDeleteTranscriptsResponse, this, _1, _2));
LLSD args;
args["FOLDER"] = gDirUtilp->getUserName();
LLNotificationsUtil::add("PreferenceChatDeleteTranscripts", args, LLSD(), boost::bind(&LLFloaterPreference::onDeleteTranscriptsResponse, this, _1, _2));
}
void LLFloaterPreference::onDeleteTranscriptsResponse(const LLSD& notification, const LLSD& response)

View File

@ -154,6 +154,7 @@ static void on_avatar_name_cache_toast(const LLUUID& agent_id,
args["FROM"] = av_name.getCompleteName();
args["FROM_ID"] = msg["from_id"];
args["SESSION_ID"] = msg["session_id"];
args["SESSION_TYPE"] = msg["session_type"];
LLNotificationsUtil::add("IMToast", args, args, boost::bind(&LLFloaterIMContainer::showConversation, LLFloaterIMContainer::getInstance(), msg["session_id"].asUUID()));
}
@ -199,13 +200,13 @@ void on_new_message(const LLSD& msg)
// execution of the action
LLFloaterIMContainer* im_box = LLFloaterReg::getTypedInstance<LLFloaterIMContainer>("im_container");
if (im_box->isFrontmost() && im_box->getSelectedSession() == session_id)
LLFloaterIMSessionTab* session_floater = LLFloaterIMSessionTab::getConversation(session_id);
if (im_box->isFrontmost() && im_box->getSelectedSession() == session_id
&& !(session_floater->getHost() ? im_box->isMinimized() : session_floater->isMinimized()))
{
return;
}
LLFloaterIMSessionTab* session_floater = LLFloaterIMSessionTab::getConversation(session_id);
//session floater not focused (visible or not)
bool session_floater_not_focused = session_floater && !session_floater->hasFocus();
@ -226,17 +227,18 @@ void on_new_message(const LLSD& msg)
&& !session_floater->isMinimized()
&& !(session_floater->getHost() && session_floater->getHost()->isMinimized());
if ("toast" == action && !session_floater_is_open)
bool conversation_floater_collapsed = !session_floater->isMessagePaneExpanded();
if (("toast" == action && !session_floater_is_open) || conversation_floater_collapsed)
{
//User is not focused on conversation containing the message
if(session_floater_not_focused)
if(session_floater_not_focused || conversation_floater_collapsed)
{
if(!LLMuteList::getInstance()->isMuted(participant_id))
{
im_box->flashConversationItemWidget(session_id, true);
}
//The conversation floater isn't focused/open
if(conversation_floater_not_focused)
if(conversation_floater_not_focused || conversation_floater_collapsed)
{
if(!LLMuteList::getInstance()->isMuted(participant_id)
&& !gAgent.isDoNotDisturb())
@ -285,6 +287,24 @@ void on_new_message(const LLSD& msg)
{
//Surface conversations floater
LLFloaterReg::showInstance("im_container");
im_box->collapseMessagesPane(false);
if (session_floater)
{
if (session_floater->getHost())
{
if (NULL != im_box && im_box->isMinimized())
{
LLFloater::onClickMinimize(im_box);
}
}
else
{
if (session_floater->isMinimized())
{
LLFloater::onClickMinimize(session_floater);
}
}
}
}
//If in DND mode, allow notification to be stored so upon DND exit
@ -636,8 +656,7 @@ void LLIMModel::LLIMSession::loadHistory()
LLIMModel::LLIMSession* LLIMModel::findIMSession(const LLUUID& session_id) const
{
return get_if_there(mId2SessionMap, session_id,
(LLIMModel::LLIMSession*) NULL);
return get_if_there(mId2SessionMap, session_id, (LLIMModel::LLIMSession*) NULL);
}
//*TODO consider switching to using std::set instead of std::list for holding LLUUIDs across the whole code
@ -990,6 +1009,7 @@ bool LLIMModel::addMessage(const LLUUID& session_id, const std::string& from, co
arg["from"] = from;
arg["from_id"] = from_id;
arg["time"] = LLLogChat::timestamp(false);
arg["session_type"] = session->mSessionType;
mNewMsgSignal(arg);
return true;
@ -2638,7 +2658,7 @@ void LLIMMgr::addMessage(
if (gSavedSettings.getBOOL("VoiceCallsFriendsOnly"))
{
// Evaluate if we need to skip this message when that setting is true (default is false)
LLIMModel::LLIMSession* session = LLIMModel::instance().findIMSession(session_id);
LLIMModel::LLIMSession* session = LLIMModel::instance().findIMSession(new_session_id);
skip_message = (LLAvatarTracker::instance().getBuddyInfo(other_participant_id) == NULL); // Skip non friends...
skip_message &= !session->isGroupSessionType(); // Do not skip group chats...
skip_message &= !(other_participant_id == gAgentID); // You are your best friend... Don't skip yourself
@ -2654,7 +2674,7 @@ void LLIMMgr::addMessage(
{
LLFloaterReg::showInstance("im_container");
LLFloaterReg::getTypedInstance<LLFloaterIMContainer>("im_container")->
flashConversationItemWidget(session_id, true);
flashConversationItemWidget(new_session_id, true);
}
}
@ -2809,7 +2829,7 @@ LLUUID LLIMMgr::addSession(
}
}
bool new_session = !LLIMModel::getInstance()->findIMSession(session_id);
bool new_session = (LLIMModel::getInstance()->findIMSession(session_id) == NULL);
//works only for outgoing ad-hoc sessions
if (new_session && IM_SESSION_CONFERENCE_START == dialog && ids.size())

View File

@ -444,7 +444,7 @@ std::string LLLogChat::oldLogFileName(std::string filename)
}
// static
void LLLogChat::getListOfTranscriptFiles(std::vector<std::string>& list_of_transcriptions)
void LLLogChat::findTranscriptFiles(std::string pattern, std::vector<std::string>& list_of_transcriptions)
{
// get Users log directory
std::string dirname = gDirUtilp->getPerAccountChatLogsDir();
@ -452,9 +452,6 @@ void LLLogChat::getListOfTranscriptFiles(std::vector<std::string>& list_of_trans
// add final OS dependent delimiter
dirname += gDirUtilp->getDirDelimiter();
// create search pattern
std::string pattern = "*." + LL_TRANSCRIPT_FILE_EXTENSION;
LLDirIterator iter(dirname, pattern);
std::string filename;
while (iter.next(filename))
@ -490,6 +487,22 @@ void LLLogChat::getListOfTranscriptFiles(std::vector<std::string>& list_of_trans
}
}
// static
void LLLogChat::getListOfTranscriptFiles(std::vector<std::string>& list_of_transcriptions)
{
// create search pattern
std::string pattern = "*." + LL_TRANSCRIPT_FILE_EXTENSION;
findTranscriptFiles(pattern, list_of_transcriptions);
}
// static
void LLLogChat::getListOfTranscriptBackupFiles(std::vector<std::string>& list_of_transcriptions)
{
// create search pattern
std::string pattern = "*." + LL_TRANSCRIPT_FILE_EXTENSION + ".backup*";
findTranscriptFiles(pattern, list_of_transcriptions);
}
//static
boost::signals2::connection LLLogChat::setSaveHistorySignal(const save_history_signal_t::slot_type& cb)
{
@ -581,6 +594,7 @@ void LLLogChat::deleteTranscripts()
{
std::vector<std::string> list_of_transcriptions;
getListOfTranscriptFiles(list_of_transcriptions);
getListOfTranscriptBackupFiles(list_of_transcriptions);
BOOST_FOREACH(const std::string& fullpath, list_of_transcriptions)
{

View File

@ -49,7 +49,9 @@ public:
const std::string& from,
const LLUUID& from_id,
const std::string& line);
static void findTranscriptFiles(std::string pattern, std::vector<std::string>& list_of_transcriptions);
static void getListOfTranscriptFiles(std::vector<std::string>& list);
static void getListOfTranscriptBackupFiles(std::vector<std::string>& list_of_transcriptions);
static void loadChatHistory(const std::string& file_name, std::list<LLSD>& messages, const LLSD& load_params = LLSD());

View File

@ -611,10 +611,10 @@ BOOL LLPanelPeople::postBuild()
mGroupList->setNoItemsMsg(getString("no_groups_msg"));
mGroupList->setNoFilteredItemsMsg(getString("no_filtered_groups_msg"));
mNearbyList->setContextMenu(&LLPanelPeopleMenus::gNearbyMenu);
mRecentList->setContextMenu(&LLPanelPeopleMenus::gNearbyMenu);
mAllFriendList->setContextMenu(&LLPanelPeopleMenus::gNearbyMenu);
mOnlineFriendList->setContextMenu(&LLPanelPeopleMenus::gNearbyMenu);
mNearbyList->setContextMenu(&LLPanelPeopleMenus::gNearbyPeopleContextMenu);
mRecentList->setContextMenu(&LLPanelPeopleMenus::gPeopleContextMenu);
mAllFriendList->setContextMenu(&LLPanelPeopleMenus::gPeopleContextMenu);
mOnlineFriendList->setContextMenu(&LLPanelPeopleMenus::gPeopleContextMenu);
setSortOrder(mRecentList, (ESortOrder)gSavedSettings.getU32("RecentPeopleSortOrder"), false);
setSortOrder(mAllFriendList, (ESortOrder)gSavedSettings.getU32("FriendsSortOrder"), false);
@ -1143,7 +1143,10 @@ void LLPanelPeople::onGearButtonClicked(LLUICtrl* btn)
uuid_vec_t selected_uuids;
getCurrentItemIDs(selected_uuids);
// Spawn at bottom left corner of the button.
LLPanelPeopleMenus::gNearbyMenu.show(btn, selected_uuids, 0, 0);
if (getActiveTabName() == NEARBY_TAB_NAME)
LLPanelPeopleMenus::gNearbyPeopleContextMenu.show(btn, selected_uuids, 0, 0);
else
LLPanelPeopleMenus::gPeopleContextMenu.show(btn, selected_uuids, 0, 0);
}
void LLPanelPeople::onImButtonClicked()

View File

@ -39,15 +39,18 @@
#include "llcallingcard.h" // for LLAvatarTracker
#include "lllogchat.h"
#include "llviewermenu.h" // for gMenuHolder
#include "llconversationmodel.h"
#include "llviewerobjectlist.h"
namespace LLPanelPeopleMenus
{
NearbyMenu gNearbyMenu;
PeopleContextMenu gPeopleContextMenu;
NearbyPeopleContextMenu gNearbyPeopleContextMenu;
//== NearbyMenu ===============================================================
//== PeopleContextMenu ===============================================================
LLContextMenu* NearbyMenu::createMenu()
LLContextMenu* PeopleContextMenu::createMenu()
{
// set up the callbacks for all of the avatar menu items
LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar;
@ -64,7 +67,8 @@ LLContextMenu* NearbyMenu::createMenu()
registrar.add("Avatar.RemoveFriend", boost::bind(&LLAvatarActions::removeFriendDialog, id));
registrar.add("Avatar.IM", boost::bind(&LLAvatarActions::startIM, id));
registrar.add("Avatar.Call", boost::bind(&LLAvatarActions::startCall, id));
registrar.add("Avatar.OfferTeleport", boost::bind(&NearbyMenu::offerTeleport, this));
registrar.add("Avatar.OfferTeleport", boost::bind(&PeopleContextMenu::offerTeleport, this));
registrar.add("Avatar.ZoomIn", boost::bind(&handle_zoom_to_object, id));
registrar.add("Avatar.ShowOnMap", boost::bind(&LLAvatarActions::showOnMap, id));
registrar.add("Avatar.Share", boost::bind(&LLAvatarActions::share, id));
registrar.add("Avatar.Pay", boost::bind(&LLAvatarActions::pay, id));
@ -72,33 +76,72 @@ LLContextMenu* NearbyMenu::createMenu()
registrar.add("Avatar.InviteToGroup", boost::bind(&LLAvatarActions::inviteToGroup, id));
registrar.add("Avatar.Calllog", boost::bind(&LLAvatarActions::viewChatHistory, id));
enable_registrar.add("Avatar.EnableItem", boost::bind(&NearbyMenu::enableContextMenuItem, this, _2));
enable_registrar.add("Avatar.CheckItem", boost::bind(&NearbyMenu::checkContextMenuItem, this, _2));
enable_registrar.add("Avatar.EnableItem", boost::bind(&PeopleContextMenu::enableContextMenuItem, this, _2));
enable_registrar.add("Avatar.CheckItem", boost::bind(&PeopleContextMenu::checkContextMenuItem, this, _2));
// create the context menu from the XUI
menu = createFromFile("menu_people_nearby.xml");
buildContextMenu(*menu, 0x0);
}
else
{
// Set up for multi-selected People
// registrar.add("Avatar.AddFriend", boost::bind(&LLAvatarActions::requestFriendshipDialog, mUUIDs)); // *TODO: unimplemented
registrar.add("Avatar.IM", boost::bind(&LLAvatarActions::startConference, mUUIDs, LLUUID::null));
registrar.add("Avatar.Call", boost::bind(&LLAvatarActions::startAdhocCall, mUUIDs, LLUUID::null));
registrar.add("Avatar.OfferTeleport", boost::bind(&NearbyMenu::offerTeleport, this));
registrar.add("Avatar.RemoveFriend",boost::bind(&LLAvatarActions::removeFriendsDialog, mUUIDs));
registrar.add("Avatar.IM", boost::bind(&LLAvatarActions::startConference, mUUIDs, LLUUID::null));
registrar.add("Avatar.Call", boost::bind(&LLAvatarActions::startAdhocCall, mUUIDs, LLUUID::null));
registrar.add("Avatar.OfferTeleport", boost::bind(&PeopleContextMenu::offerTeleport, this));
registrar.add("Avatar.RemoveFriend", boost::bind(&LLAvatarActions::removeFriendsDialog, mUUIDs));
// registrar.add("Avatar.Share", boost::bind(&LLAvatarActions::startIM, mUUIDs)); // *TODO: unimplemented
// registrar.add("Avatar.Pay", boost::bind(&LLAvatarActions::pay, mUUIDs)); // *TODO: unimplemented
enable_registrar.add("Avatar.EnableItem", boost::bind(&NearbyMenu::enableContextMenuItem, this, _2));
// registrar.add("Avatar.Pay", boost::bind(&LLAvatarActions::pay, mUUIDs)); // *TODO: unimplemented
enable_registrar.add("Avatar.EnableItem", boost::bind(&PeopleContextMenu::enableContextMenuItem, this, _2));
// create the context menu from the XUI
menu = createFromFile("menu_people_nearby_multiselect.xml");
buildContextMenu(*menu, ITEM_IN_MULTI_SELECTION);
}
return menu;
}
bool NearbyMenu::enableContextMenuItem(const LLSD& userdata)
void PeopleContextMenu::buildContextMenu(class LLMenuGL& menu, U32 flags)
{
menuentry_vec_t items;
menuentry_vec_t disabled_items;
if (flags & ITEM_IN_MULTI_SELECTION)
{
items.push_back(std::string("add_friends"));
items.push_back(std::string("remove_friends"));
items.push_back(std::string("im"));
items.push_back(std::string("call"));
items.push_back(std::string("share"));
items.push_back(std::string("pay"));
items.push_back(std::string("offer_teleport"));
}
else
{
items.push_back(std::string("view_profile"));
items.push_back(std::string("im"));
items.push_back(std::string("offer_teleport"));
items.push_back(std::string("voice_call"));
items.push_back(std::string("chat_history"));
items.push_back(std::string("separator_chat_history"));
items.push_back(std::string("add_friend"));
items.push_back(std::string("remove_friend"));
items.push_back(std::string("invite_to_group"));
items.push_back(std::string("separator_invite_to_group"));
items.push_back(std::string("map"));
items.push_back(std::string("share"));
items.push_back(std::string("pay"));
items.push_back(std::string("block_unblock"));
}
hide_context_entries(menu, items, disabled_items);
}
bool PeopleContextMenu::enableContextMenuItem(const LLSD& userdata)
{
if(gAgent.getID() == mUUIDs.front())
{
@ -170,6 +213,12 @@ bool NearbyMenu::enableContextMenuItem(const LLSD& userdata)
{
return LLAvatarActions::canCall();
}
else if (item == std::string("can_zoom_in"))
{
const LLUUID& id = mUUIDs.front();
return gObjectList.findObject(id);
}
else if (item == std::string("can_show_on_map"))
{
const LLUUID& id = mUUIDs.front();
@ -193,7 +242,7 @@ bool NearbyMenu::enableContextMenuItem(const LLSD& userdata)
return false;
}
bool NearbyMenu::checkContextMenuItem(const LLSD& userdata)
bool PeopleContextMenu::checkContextMenuItem(const LLSD& userdata)
{
std::string item = userdata.asString();
const LLUUID& id = mUUIDs.front();
@ -206,11 +255,50 @@ bool NearbyMenu::checkContextMenuItem(const LLSD& userdata)
return false;
}
void NearbyMenu::offerTeleport()
void PeopleContextMenu::offerTeleport()
{
// boost::bind cannot recognize overloaded method LLAvatarActions::offerTeleport(),
// so we have to use a wrapper.
LLAvatarActions::offerTeleport(mUUIDs);
}
//== NearbyPeopleContextMenu ===============================================================
void NearbyPeopleContextMenu::buildContextMenu(class LLMenuGL& menu, U32 flags)
{
menuentry_vec_t items;
menuentry_vec_t disabled_items;
if (flags & ITEM_IN_MULTI_SELECTION)
{
items.push_back(std::string("add_friends"));
items.push_back(std::string("remove_friends"));
items.push_back(std::string("im"));
items.push_back(std::string("call"));
items.push_back(std::string("share"));
items.push_back(std::string("pay"));
items.push_back(std::string("offer_teleport"));
}
else
{
items.push_back(std::string("view_profile"));
items.push_back(std::string("im"));
items.push_back(std::string("offer_teleport"));
items.push_back(std::string("voice_call"));
items.push_back(std::string("chat_history"));
items.push_back(std::string("separator_chat_history"));
items.push_back(std::string("add_friend"));
items.push_back(std::string("remove_friend"));
items.push_back(std::string("invite_to_group"));
items.push_back(std::string("separator_invite_to_group"));
items.push_back(std::string("zoom_in"));
items.push_back(std::string("map"));
items.push_back(std::string("share"));
items.push_back(std::string("pay"));
items.push_back(std::string("block_unblock"));
}
hide_context_entries(menu, items, disabled_items);
}
} // namespace LLPanelPeopleMenus

View File

@ -33,19 +33,33 @@ namespace LLPanelPeopleMenus
{
/**
* Menu used in the nearby people list.
* Menu used in the people lists.
*/
class NearbyMenu : public LLListContextMenu
class PeopleContextMenu : public LLListContextMenu
{
public:
/*virtual*/ LLContextMenu* createMenu();
protected:
virtual void buildContextMenu(class LLMenuGL& menu, U32 flags);
private:
bool enableContextMenuItem(const LLSD& userdata);
bool checkContextMenuItem(const LLSD& userdata);
void offerTeleport();
};
extern NearbyMenu gNearbyMenu;
/**
* Menu used in the nearby people list.
*/
class NearbyPeopleContextMenu : public PeopleContextMenu
{
protected:
/*virtual*/ void buildContextMenu(class LLMenuGL& menu, U32 flags);
};
extern PeopleContextMenu gPeopleContextMenu;
extern NearbyPeopleContextMenu gNearbyPeopleContextMenu;
} // namespace LLPanelPeopleMenus

View File

@ -38,6 +38,8 @@
#include "llvoavatar.h"
#include "llworld.h"
extern LLControlGroup gSavedSettings;
const LLColor4 INACTIVE_COLOR(0.3f, 0.3f, 0.3f, 0.5f);
const LLColor4 ACTIVE_COLOR(0.5f, 0.5f, 0.5f, 1.f);
@ -311,6 +313,7 @@ LLSpeakerMgr::LLSpeakerMgr(LLVoiceChannel* channelp) :
mModerateModeHandledFirstTime(false),
mSpeakerListUpdated(false)
{
mGetListTime.reset();
static LLUICachedControl<F32> remove_delay ("SpeakerParticipantRemoveDelay", 10.0);
mSpeakerDelayRemover = new LLSpeakersDelayActionsStorage(boost::bind(&LLSpeakerMgr::removeSpeaker, this, _1), remove_delay);
@ -409,12 +412,10 @@ void LLSpeakerMgr::update(BOOL resort_ok)
// update status of all current speakers
BOOL voice_channel_active = (!mVoiceChannel && LLVoiceClient::getInstance()->inProximalChannel()) || (mVoiceChannel && mVoiceChannel->isActive());
for (speaker_map_t::iterator speaker_it = mSpeakers.begin(); speaker_it != mSpeakers.end();)
for (speaker_map_t::iterator speaker_it = mSpeakers.begin(); speaker_it != mSpeakers.end(); speaker_it++)
{
LLUUID speaker_id = speaker_it->first;
LLSpeaker* speakerp = speaker_it->second;
speaker_it++;
if (voice_channel_active && LLVoiceClient::getInstance()->getVoiceEnabled(speaker_id))
{
@ -539,30 +540,39 @@ void LLSpeakerMgr::updateSpeakerList()
LLIMModel::LLIMSession* session = LLIMModel::getInstance()->findIMSession(session_id);
if (session->isGroupSessionType() && (mSpeakers.size() <= 1))
{
const F32 load_group_timeout = gSavedSettings.getF32("ChatLoadGroupTimeout");
// For groups, we need to hit the group manager.
// Note: The session uuid and the group uuid are actually one and the same. If that was to change, this will fail.
LLGroupMgrGroupData* gdatap = LLGroupMgr::getInstance()->getGroupData(session_id);
if (!gdatap)
if (!gdatap && (mGetListTime.getElapsedTimeF32() >= load_group_timeout))
{
// Request the data the first time around
LLGroupMgr::getInstance()->sendCapGroupMembersRequest(session_id);
}
else if (gdatap->isMemberDataComplete() && !gdatap->mMembers.empty())
else if (gdatap && gdatap->isMemberDataComplete() && !gdatap->mMembers.empty())
{
// Add group members when we get the complete list (note: can take a while before we get that list)
LLGroupMgrGroupData::member_list_t::iterator member_it = gdatap->mMembers.begin();
const S32 load_group_max_members = gSavedSettings.getS32("ChatLoadGroupMaxMembers");
S32 updated = 0;
while (member_it != gdatap->mMembers.end())
{
LLGroupMemberData* member = member_it->second;
// Add only the members who are online
if (member->getOnlineStatus() == "Online")
LLUUID id = member_it->first;
// Add only members who are online and not already in the list
if ((member->getOnlineStatus() == "Online") && (mSpeakers.find(id) == mSpeakers.end()))
{
LLPointer<LLSpeaker> speakerp = setSpeaker(member_it->first, "", LLSpeaker::STATUS_VOICE_ACTIVE, LLSpeaker::SPEAKER_AGENT);
LLPointer<LLSpeaker> speakerp = setSpeaker(id, "", LLSpeaker::STATUS_VOICE_ACTIVE, LLSpeaker::SPEAKER_AGENT);
speakerp->mIsModerator = ((member->getAgentPowers() & GP_SESSION_MODERATOR) == GP_SESSION_MODERATOR);
updated++;
}
++member_it;
// Limit the number of "manually updated" participants to a reasonable number to avoid severe fps drop
// *TODO : solve the perf issue of having several hundreds of widgets in the conversation list
if (updated >= load_group_max_members)
break;
}
mSpeakerListUpdated = true;
mSpeakerListUpdated = true;
}
}
else if (mSpeakers.size() == 0)

View File

@ -264,6 +264,7 @@ protected:
typedef std::map<LLUUID, LLPointer<LLSpeaker> > speaker_map_t;
speaker_map_t mSpeakers;
bool mSpeakerListUpdated;
LLTimer mGetListTime;
speaker_list_t mSpeakersSorted;
LLFrameTimer mSpeechTimer;

View File

@ -1038,7 +1038,6 @@ void render_hud_attachments()
if (LLPipeline::sShowHUDAttachments && !gDisconnected && setup_hud_matrices())
{
LLCamera hud_cam = *LLViewerCamera::getInstance();
//LLVector3 origin = hud_cam.getOrigin();
hud_cam.setOrigin(-1.f,0,0);
hud_cam.setAxes(LLVector3(1,0,0), LLVector3(0,1,0), LLVector3(0,0,1));
LLViewerCamera::updateFrustumPlanes(hud_cam, TRUE);

View File

@ -2379,7 +2379,7 @@ void process_improved_im(LLMessageSystem *msg, void **user_data)
LLPostponedNotification::add<LLPostponedIMSystemTipNotification>(params, from_id, false);
break;
case IM_NOTHING_SPECIAL:
case IM_NOTHING_SPECIAL: // p2p IM
// Don't show dialog, just do IM
if (!gAgent.isGodlike()
&& gAgent.getRegion()->isPrelude()
@ -2780,42 +2780,6 @@ void process_improved_im(LLMessageSystem *msg, void **user_data)
}
break;
case IM_SESSION_SEND:
{
if (is_do_not_disturb)
{
return;
}
// Only show messages if we have a session open (which
// should happen after you get an "invitation"
if ( !gIMMgr->hasSession(session_id) )
{
return;
}
// standard message, not from system
std::string saved;
if(offline == IM_OFFLINE)
{
saved = llformat("(Saved %s) ", formatted_time(timestamp).c_str());
}
buffer = saved + message;
gIMMgr->addMessage(
session_id,
from_id,
name,
buffer,
IM_OFFLINE == offline,
ll_safe_string((char*)binary_bucket),
IM_SESSION_INVITE,
parent_estate_id,
region_id,
position,
true);
}
break;
case IM_FROM_TASK:
{
if (is_do_not_disturb && !is_owned_by_me)
@ -2914,6 +2878,76 @@ void process_improved_im(LLMessageSystem *msg, void **user_data)
LLPostponedNotification::add<LLPostponedServerObjectNotification>(params, from_id, from_group);
}
break;
case IM_SESSION_SEND: // ad-hoc or group IMs
// Only show messages if we have a session open (which
// should happen after you get an "invitation"
if ( !gIMMgr->hasSession(session_id) )
{
return;
}
else if (offline == IM_ONLINE && is_do_not_disturb)
{
// return a standard "do not disturb" message, but only do it to online IM
// (i.e. not other auto responses and not store-and-forward IM)
if (!gIMMgr->hasSession(session_id))
{
// if there is not a panel for this conversation (i.e. it is a new IM conversation
// initiated by the other party) then...
send_do_not_disturb_message(msg, from_id, session_id);
}
// now store incoming IM in chat history
buffer = message;
LL_INFOS("Messaging") << "process_improved_im: session_id( " << session_id << " ), from_id( " << from_id << " )" << LL_ENDL;
// add to IM panel, but do not bother the user
gIMMgr->addMessage(
session_id,
from_id,
name,
buffer,
IM_OFFLINE == offline,
ll_safe_string((char*)binary_bucket),
IM_SESSION_INVITE,
parent_estate_id,
region_id,
position,
true);
}
else
{
// standard message, not from system
std::string saved;
if(offline == IM_OFFLINE)
{
saved = llformat("(Saved %s) ", formatted_time(timestamp).c_str());
}
buffer = saved + message;
LL_INFOS("Messaging") << "process_improved_im: session_id( " << session_id << " ), from_id( " << from_id << " )" << LL_ENDL;
gIMMgr->addMessage(
session_id,
from_id,
name,
buffer,
IM_OFFLINE == offline,
ll_safe_string((char*)binary_bucket),
IM_SESSION_INVITE,
parent_estate_id,
region_id,
position,
true);
}
break;
case IM_FROM_TASK_AS_ALERT:
if (is_do_not_disturb && !is_owned_by_me)
{

View File

@ -2837,7 +2837,6 @@ void LLViewerWindow::updateUI()
BOOL handled = FALSE;
//BOOL handled_by_top_ctrl = FALSE;
LLUICtrl* top_ctrl = gFocusMgr.getTopCtrl();
LLMouseHandler* mouse_captor = gFocusMgr.getMouseCapture();
LLView* captor_view = dynamic_cast<LLView*>(mouse_captor);
@ -3022,7 +3021,6 @@ void LLViewerWindow::updateUI()
S32 local_x, local_y;
top_ctrl->screenPointToLocal( x, y, &local_x, &local_y );
handled = top_ctrl->pointInView(local_x, local_y) && top_ctrl->handleHover(local_x, local_y, mask);
//handled_by_top_ctrl = TRUE;
}
if ( !handled )

View File

@ -2533,43 +2533,43 @@ void LLVOAvatar::idleUpdateNameTag(const LLVector3& root_pos_last)
return;
}
BOOL new_name = FALSE;
if (visible_chat != mVisibleChat)
{
mVisibleChat = visible_chat;
new_name = TRUE;
}
if (sRenderGroupTitles != mRenderGroupTitles)
{
mRenderGroupTitles = sRenderGroupTitles;
new_name = TRUE;
}
BOOL new_name = FALSE;
if (visible_chat != mVisibleChat)
{
mVisibleChat = visible_chat;
new_name = TRUE;
}
// First Calculate Alpha
// If alpha > 0, create mNameText if necessary, otherwise delete it
F32 alpha = 0.f;
if (mAppAngle > 5.f)
{
const F32 START_FADE_TIME = NAME_SHOW_TIME - FADE_DURATION;
if (!visible_chat && sRenderName == RENDER_NAME_FADE && time_visible > START_FADE_TIME)
{
alpha = 1.f - (time_visible - START_FADE_TIME) / FADE_DURATION;
}
else
{
// ...not fading, full alpha
alpha = 1.f;
}
}
else if (mAppAngle > 2.f)
{
// far away is faded out also
alpha = (mAppAngle-2.f)/3.f;
}
if (sRenderGroupTitles != mRenderGroupTitles)
{
mRenderGroupTitles = sRenderGroupTitles;
new_name = TRUE;
}
// First Calculate Alpha
// If alpha > 0, create mNameText if necessary, otherwise delete it
F32 alpha = 0.f;
if (mAppAngle > 5.f)
{
const F32 START_FADE_TIME = NAME_SHOW_TIME - FADE_DURATION;
if (!visible_chat && sRenderName == RENDER_NAME_FADE && time_visible > START_FADE_TIME)
{
alpha = 1.f - (time_visible - START_FADE_TIME) / FADE_DURATION;
}
else
{
// ...not fading, full alpha
alpha = 1.f;
}
}
else if (mAppAngle > 2.f)
{
// far away is faded out also
alpha = (mAppAngle-2.f)/3.f;
}
if (alpha <= 0.f)
{
{
if (mNameText)
{
mNameText->markDead();
@ -2579,19 +2579,19 @@ void LLVOAvatar::idleUpdateNameTag(const LLVector3& root_pos_last)
return;
}
if (!mNameText)
{
if (!mNameText)
{
mNameText = static_cast<LLHUDNameTag*>( LLHUDObject::addHUDObject(
LLHUDObject::LL_HUD_NAME_TAG) );
//mNameText->setMass(10.f);
mNameText->setSourceObject(this);
mNameText->setSourceObject(this);
mNameText->setVertAlignment(LLHUDNameTag::ALIGN_VERT_TOP);
mNameText->setVisibleOffScreen(TRUE);
mNameText->setMaxLines(11);
mNameText->setFadeDistance(CHAT_NORMAL_RADIUS, 5.f);
sNumVisibleChatBubbles++;
new_name = TRUE;
}
mNameText->setVisibleOffScreen(TRUE);
mNameText->setMaxLines(11);
mNameText->setFadeDistance(CHAT_NORMAL_RADIUS, 5.f);
sNumVisibleChatBubbles++;
new_name = TRUE;
}
idleUpdateNameTagPosition(root_pos_last);
idleUpdateNameTagText(new_name);
@ -2636,6 +2636,7 @@ void LLVOAvatar::idleUpdateNameTagText(BOOL new_name)
// Rebuild name tag if state change detected
if (mNameString.empty()
|| (mNameString.size() == 2 && mNameString[0] == 10 && mNameString[1] == 10) // *TODO : find out why mNameString is sometimes ""
|| new_name
|| (!title && !mTitle.empty())
|| (title && mTitle != title->getString())
@ -2840,6 +2841,7 @@ void LLVOAvatar::clearNameTag()
mNameText->setLabel("");
mNameText->setString( "" );
}
mTimeVisible.reset();
}
//static

View File

@ -965,8 +965,6 @@ void LLWorldMapView::drawTracking(const LLVector3d& pos_global, const LLColor4&
S32 text_x = x;
S32 text_y = (S32)(y - sTrackCircleImage->getHeight()/2 - font->getLineHeight());
//BOOL is_in_window = true;
if( x < 0
|| y < 0
|| x >= getRect().getWidth()
@ -979,7 +977,6 @@ void LLWorldMapView::drawTracking(const LLVector3d& pos_global, const LLColor4&
text_x = sTrackingArrowX;
text_y = sTrackingArrowY;
}
//is_in_window = false;
}
else if (LLTracker::getTrackingStatus() == LLTracker::TRACKING_LOCATION &&
LLTracker::getTrackedLocationType() != LLTracker::LOCATION_NOTHING)

Binary file not shown.

After

Width:  |  Height:  |  Size: 538 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 545 B

View File

@ -171,6 +171,8 @@ with the same filename but different name
<texture name="Conv_toolbar_call_log" file_name="icons/Conv_toolbar_call_log.png" preload="false" />
<texture name="Conv_toolbar_close" file_name="icons/Conv_toolbar_close.png" preload="false" />
<texture name="Conv_toolbar_collapse" file_name="icons/Conv_toolbar_collapse.png" preload="false" />
<texture name="Conv_collapse_to_one_line" file_name="icons/collapse_to_one_line.png" preload="false" />
<texture name="Conv_expand_one_line" file_name="icons/expand_one_liner.png" preload="false" />
<texture name="Conv_toolbar_expand" file_name="icons/Conv_toolbar_expand.png" preload="false" />
<texture name="Conv_toolbar_hang_up" file_name="icons/Conv_toolbar_hang_up.png" preload="false" />
<texture name="Conv_toolbar_open_call" file_name="icons/Conv_toolbar_open_call.png" preload="false" />

View File

@ -61,7 +61,7 @@
image_unselected="Toolbar_Middle_Off"
menu_filename="menu_participant_view.xml"
layout="topleft"
left="10"
left="5"
name="sort_btn"
tool_tip="View/sort options"
top="5"
@ -75,7 +75,7 @@
image_unselected="Toolbar_Middle_Off"
layout="topleft"
top="5"
left_pad="4"
left_pad="2"
name="add_btn"
tool_tip="Start a new conversation"
width="31"/>
@ -88,7 +88,7 @@
image_unselected="Toolbar_Middle_Off"
layout="topleft"
top="5"
left_pad="4"
left_pad="2"
name="speak_btn"
tool_tip="Speak with people using your microphone"
width="31"/>
@ -114,7 +114,7 @@
</layout_panel>
</layout_stack>
<panel
bottom="-5"
bottom="-1"
follows="all"
layout="topleft"
name="conversations_list_panel"
@ -129,7 +129,7 @@
name="messages_layout_panel"
expanded_min_dim="222">
<panel_container
bottom="-5"
bottom="-1"
follows="all"
layout="topleft"
left="0"

View File

@ -19,6 +19,12 @@
positioning="relative">
<floater.string name="call_btn_start">Conv_toolbar_open_call</floater.string>
<floater.string name="call_btn_stop">Conv_toolbar_hang_up</floater.string>
<floater.string
name="collapseline_icon"
value="Conv_collapse_to_one_line"/>
<floater.string
name="expandline_icon"
value="Conv_expand_one_line"/>
<floater.string
name="collapse_icon"
value="Conv_toolbar_collapse"/>
@ -65,14 +71,28 @@
top="0"
left="0"
height="355"
width="394">
<panel
width="394">
<layout_stack
animate="false"
default_tab_group="2"
follows="all"
height="355"
width="394"
layout="topleft"
orientation="vertical"
name="main_stack"
tab_group="1"
top="0"
left="0">
<layout_panel
follows="left|top|right"
layout="topleft"
name="toolbar_panel"
top="0"
left="0"
height="35"
min_height="35"
width="394">
<menu_button
menu_filename="menu_im_session_showmodes.xml"
@ -98,7 +118,7 @@
image_unselected="Toolbar_Middle_Off"
layout="topleft"
top="5"
left_pad="4"
left_pad="2"
name="gear_btn"
visible="false"
tool_tip="Actions on selected person"
@ -113,7 +133,7 @@
image_unselected="Toolbar_Middle_Off"
layout="topleft"
top="5"
left_pad="4"
left_pad="2"
name="add_btn"
tool_tip="Add someone to this conversation"
width="31"/>
@ -126,7 +146,7 @@
image_unselected="Toolbar_Middle_Off"
layout="topleft"
top="5"
left_pad="4"
left_pad="2"
name="voice_call_btn"
tool_tip="Open voice connection"
width="31"/>
@ -151,7 +171,7 @@
image_unselected="Toolbar_Middle_Off"
layout="topleft"
top="5"
left="283"
left="292"
name="close_btn"
tool_tip="End this conversation"
width="31" />
@ -164,7 +184,7 @@
image_unselected="Toolbar_Middle_Off"
layout="topleft"
top="5"
left_pad="5"
left_pad="2"
name="expand_collapse_btn"
tool_tip="Collapse/Expand this pane"
width="31" />
@ -177,15 +197,22 @@
image_unselected="Toolbar_Middle_Off"
layout="topleft"
top="5"
left_pad="5"
left_pad="2"
name="tear_off_btn"
width="31" />
</panel>
</layout_panel>
<layout_panel
name="body_panel"
follows="all"
width="394"
height="235"
user_resize="false"
auto_resize="true">
<layout_stack
animate="true"
default_tab_group="2"
follows="all"
height="310"
height="275"
width="394"
layout="topleft"
orientation="horizontal"
@ -198,9 +225,9 @@
follows="all"
min_width="115"
width="150"
height="310"
height="275"
user_resize="true"
auto_resize="true">
auto_resize="false">
</layout_panel>
<layout_panel
default_tab_group="3"
@ -208,7 +235,7 @@
tab_group="2"
follows="all"
top="0"
height="310"
height="275"
width="244"
layout="topleft"
user_resize="true"
@ -221,13 +248,13 @@
follows="all"
layout="topleft"
visible="true"
height="275"
height="240"
width="244">
<layout_stack
animate="true"
default_tab_group="2"
follows="all"
height="275"
height="240"
width="244"
layout="topleft"
visible="true"
@ -258,7 +285,7 @@
width="230" />
</layout_panel>
<layout_panel
height="248"
height="233"
width="210"
layout="topleft"
follows="all"
@ -273,7 +300,7 @@
font="SansSerifSmall"
follows="all"
visible="true"
height="240"
height="225"
name="chat_history"
parse_highlights="true"
parse_urls="true"
@ -283,26 +310,90 @@
</layout_panel>
</layout_stack>
</panel>
<chat_editor
</layout_panel>
</layout_stack>
</layout_panel>
<layout_panel
height="35"
layout="topleft"
follows="left|right|bottom"
left_delta="0"
right="0"
top_delta="0"
bottom="0"
visible="true"
user_resize="false"
auto_resize="false"
name="chat_layout_panel">
<layout_stack
animate="true"
default_tab_group="2"
follows="all"
height="35"
right="0"
layout="topleft"
orientation="horizontal"
name="input_panels"
top_pad="0"
left="0">
<layout_panel
height="35"
layout="topleft"
follows="left|right|bottom"
left_delta="0"
top_delta="0"
bottom="0"
visible="true"
user_resize="false"
auto_resize="true"
name="input_editor_layout_panel">
<chat_editor
top="6"
expand_lines_count="5"
follows="left|right|bottom"
font="SansSerifSmall"
font="SansSerifSmall"
visible="true"
height="20"
is_expandable="true"
label="To"
text_tentative_color="TextFgTentativeColor"
layout="bottomleft"
layout="topleft"
name="chat_editor"
max_length="1023"
spellcheck="true"
tab_group="3"
width="220"
left="10"
width="160"
left="5"
right="-5"
wrap="true">
</chat_editor>
</layout_panel>
</layout_panel>
<layout_panel
height="35"
layout="topleft"
follows="left|right|bottom"
left_delta="0"
top_delta="0"
bottom="0"
width="35"
visible="true"
user_resize="false"
auto_resize="false"
name="input_button_layout_panel">
<button
follows="left|right|bottom"
height="25"
image_hover_unselected="Toolbar_Middle_Over"
image_overlay="Conv_expand_one_line"
image_selected="Toolbar_Middle_Selected"
image_unselected="Toolbar_Middle_Off"
layout="topleft"
name="minz_btn"
tool_tip="Shows/hides message panel"
width="28"/>
</layout_panel>
</layout_stack>
</layout_panel>
</layout_stack>
</view>
</floater>

View File

@ -89,7 +89,14 @@
<on_click function="Avatar.DoToSelected" parameter="invite_to_group" />
<on_enable function="Avatar.EnableItem" parameter="can_invite" />
</menu_item_call>
<menu_item_separator layout="topleft" name="separator_invite_to_group"/>
<menu_item_separator layout="topleft" name="separator_invite_to_group"/>
<menu_item_call
label="Zoom In"
layout="topleft"
name="zoom_in">
<on_click function="Avatar.DoToSelected" parameter="zoom_in" />
<on_enable function="Avatar.EnableItem" parameter="can_zoom_in" />
</menu_item_call>
<menu_item_call
label="Map"
layout="topleft"

View File

@ -49,6 +49,13 @@
</menu_item_call>
<menu_item_separator
layout="topleft"/>
<menu_item_call
label="Zoom In"
layout="topleft"
name="zoom_in">
<on_click function="Avatar.DoToSelected" parameter="zoom_in" />
<on_enable function="Avatar.EnableItem" parameter="can_zoom_in" />
</menu_item_call>
<menu_item_call
label="Map"
layout="topleft"

View File

@ -24,4 +24,22 @@
function="ObjectIcon.Action"
parameter="block" />
</menu_item_call>
<menu_item_separator
layout="topleft" />
<menu_item_call
label="Show on Map"
layout="topleft"
name="show_on_map">
<menu_item_call.on_click
function="ObjectIcon.Action"
parameter="map" />
</menu_item_call>
<menu_item_call
label="Teleport to Object Location"
layout="topleft"
name="teleport_to_object">
<menu_item_call.on_click
function="ObjectIcon.Action"
parameter="teleport" />
</menu_item_call>
</menu>

View File

@ -1,18 +1,18 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<context_menu
layout="topleft"
name="Avatar Context Menu">
name="Nearby People Context Menu">
<menu_item_call
label="View Profile"
layout="topleft"
name="View Profile">
name="view_profile">
<menu_item_call.on_click
function="Avatar.Profile" />
</menu_item_call>
<menu_item_call
label="IM"
layout="topleft"
name="IM">
name="im">
<menu_item_call.on_click
function="Avatar.IM" />
<menu_item_call.on_enable
@ -21,7 +21,7 @@
</menu_item_call>
<menu_item_call
label="Offer Teleport"
name="teleport">
name="offer_teleport">
<menu_item_call.on_click
function="Avatar.OfferTeleport"/>
<menu_item_call.on_enable
@ -31,7 +31,7 @@
<menu_item_call
label="Voice call"
layout="topleft"
name="Call">
name="voice_call">
<menu_item_call.on_click
function="Avatar.Call" />
<menu_item_call.on_enable
@ -42,18 +42,18 @@
<menu_item_call
label="View chat history..."
layout="topleft"
name="Chat history">
name="chat_history">
<menu_item_call.on_click
function="Avatar.Calllog" />
<menu_item_call.on_enable
function="Avatar.EnableItem"
parameter="can_callog"/>
</menu_item_call>
<menu_item_separator />
<menu_item_separator name="separator_chat_history"/>
<menu_item_call
label="Add Friend"
layout="topleft"
name="Add Friend">
name="add_friend">
<menu_item_call.on_click
function="Avatar.AddFriend" />
<menu_item_call.on_visible
@ -63,7 +63,7 @@
<menu_item_call
label="Remove Friend"
layout="topleft"
name="Remove Friend">
name="remove_friend">
<menu_item_call.on_click
function="Avatar.RemoveFriend" />
<menu_item_call.on_enable
@ -73,18 +73,28 @@
<menu_item_call
label="Invite to group..."
layout="topleft"
name="Invite">
name="invite_to_group">
<menu_item_call.on_click
function="Avatar.InviteToGroup" />
<menu_item_call.on_enable
function="Avatar.EnableItem"
parameter="can_invite"/>
</menu_item_call>
<menu_item_separator />
<menu_item_separator name="separator_invite_to_group"/>
<menu_item_call
label="Zoom In"
layout="topleft"
name="zoom_in">
<menu_item_call.on_click
function="Avatar.ZoomIn" />
<menu_item_call.on_enable
function="Avatar.EnableItem"
parameter="can_zoom_in"/>
</menu_item_call>
<menu_item_call
label="Map"
layout="topleft"
name="Map">
name="map">
<menu_item_call.on_click
function="Avatar.ShowOnMap" />
<menu_item_call.on_enable
@ -94,7 +104,7 @@
<menu_item_call
label="Share"
layout="topleft"
name="Share">
name="share">
<menu_item_call.on_click
function="Avatar.Share" />
<menu_item_call.on_enable
@ -104,7 +114,7 @@
<menu_item_call
label="Pay"
layout="topleft"
name="Pay">
name="pay">
<menu_item_call.on_click
function="Avatar.Pay" />
<menu_item_call.on_enable
@ -114,7 +124,7 @@
<menu_item_check
label="Block/Unblock"
layout="topleft"
name="Block/Unblock">
name="block_unblock">
<menu_item_check.on_click
function="Avatar.BlockUnblock" />
<menu_item_check.on_check

View File

@ -6,7 +6,7 @@
enabled="false"
label="Add Friends"
layout="topleft"
name="Add Friends">
name="add_friends">
<on_click
function="Avatar.AddFriends" />
<on_enable
@ -16,7 +16,7 @@
<menu_item_call
label="Remove Friends"
layout="topleft"
name="Remove Friend">
name="remove_friends">
<menu_item_call.on_click
function="Avatar.RemoveFriend" />
<menu_item_call.on_enable
@ -26,7 +26,7 @@
<menu_item_call
label="IM"
layout="topleft"
name="IM">
name="im">
<on_click
function="Avatar.IM" />
</menu_item_call>
@ -34,7 +34,7 @@
enabled="false"
label="Call"
layout="topleft"
name="Call">
name="call">
<on_click
function="Avatar.Call" />
<on_enable
@ -45,7 +45,7 @@
enabled="false"
label="Share"
layout="topleft"
name="Share">
name="share">
<on_click
function="Avatar.Share" />
</menu_item_call>
@ -53,13 +53,13 @@
enabled="false"
label="Pay"
layout="topleft"
name="Pay">
name="pay">
<on_click
function="Avatar.Pay" />
</menu_item_call>
<menu_item_call
label="Offer Teleport"
name="teleport">
name="offer_teleport">
<menu_item_call.on_click
function="Avatar.OfferTeleport"/>
<menu_item_call.on_enable

View File

@ -1,20 +1,27 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<context_menu
layout="topleft"
name="Url Popup">
name="Url Popup">
<menu_item_call
label="Send IM"
label="View Profile"
layout="topleft"
name="show_agent">
<menu_item_call.on_click
function="Url.ShowProfile" />
</menu_item_call>
<menu_item_call
label="Send IM..."
layout="topleft"
name="send_im">
<menu_item_call.on_click
function="Url.SendIM" />
</menu_item_call>
<menu_item_call
label="Show Resident Profile"
label="Add Friend..."
layout="topleft"
name="show_agent">
name="add_friend">
<menu_item_call.on_click
function="Url.ShowProfile" />
function="Url.AddFriend" />
</menu_item_call>
<menu_item_separator
layout="topleft" />

View File

@ -7,7 +7,7 @@
layout="topleft"
name="show_group">
<menu_item_call.on_click
function="Url.Execute" />
function="Url.ShowProfile" />
</menu_item_call>
<menu_item_separator
layout="topleft" />

View File

@ -3,7 +3,7 @@
layout="topleft"
name="Url Popup">
<menu_item_call
label="Show Object Information"
label="Object Profile..."
layout="topleft"
name="show_object">
<menu_item_call.on_click

View File

@ -9998,7 +9998,7 @@ Cannot create large prims that intersect other players. Please re-try when othe
icon="alertmodal.tga"
name="PreferenceChatClearLog"
type="alertmodal">
This will delete the log of previous conversations. Proceed?
This will delete the logs of previous conversations, and any backups of that file.
<tag>confirm</tag>
<usetemplate
ignoretext="Confirm before I delete the log of previous conversations."
@ -10011,7 +10011,7 @@ Cannot create large prims that intersect other players. Please re-try when othe
icon="alertmodal.tga"
name="PreferenceChatDeleteTranscripts"
type="alertmodal">
This will delete transcripts for all previous conversations. The list of conversations will not be affected. If you run scripts on your chat transcript files, you may want to proceed with caution. Proceed?
This will delete the transcripts for all previous conversations. The list of past conversations will not be affected. All files with the suffixes .txt and txt.backup in the folder [FOLDER] will be deleted.
<tag>confirm</tag>
<usetemplate
ignoretext="Confirm before I delete transcripts."

View File

@ -429,7 +429,6 @@
</text>
<line_editor
enabled="false"
control_name="InstantMessageLogPath"
border_style="line"
border_thickness="1"