merge changes for 3.5.0-beta6
commit
130e4e5101
2
.hgtags
2
.hgtags
|
|
@ -429,3 +429,5 @@ f6ca5bb75bca975ff0bc77e71e615f6478c4559c 3.5.0-beta3
|
|||
53cffdde0b3cc367ba9bb6abd5c83ae14df5e882 3.5.0-beta4
|
||||
4d5f6234dc59a0fb6ead5e02c7d343a0610e0488 DRTVWR-304
|
||||
dd058a6093c493120d67c8e02c812c0f7b2d3db0 3.5.0-beta5
|
||||
fd6b510e83f56830e45670c428653134899d3e25 DRTVWR-305
|
||||
55339537d99afc394d1bb7fdb7d074bf321ca62f 3.5.0-beta6
|
||||
|
|
|
|||
|
|
@ -1801,6 +1801,9 @@ BOOL LLScrollListCtrl::handleRightMouseDown(S32 x, S32 y, MASK mask)
|
|||
// (N.B. callbacks don't take const refs as id is local scope)
|
||||
bool is_group = (mContextMenuType == MENU_GROUP);
|
||||
LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar;
|
||||
registrar.add("Url.ShowProfile", boost::bind(&LLScrollListCtrl::showProfile, id, is_group));
|
||||
registrar.add("Url.SendIM", boost::bind(&LLScrollListCtrl::sendIM, id));
|
||||
registrar.add("Url.AddFriend", boost::bind(&LLScrollListCtrl::addFriend, id));
|
||||
registrar.add("Url.Execute", boost::bind(&LLScrollListCtrl::showNameDetails, id, is_group));
|
||||
registrar.add("Url.CopyLabel", boost::bind(&LLScrollListCtrl::copyNameToClipboard, id, is_group));
|
||||
registrar.add("Url.CopyUrl", boost::bind(&LLScrollListCtrl::copySLURLToClipboard, id, is_group));
|
||||
|
|
@ -1821,11 +1824,33 @@ BOOL LLScrollListCtrl::handleRightMouseDown(S32 x, S32 y, MASK mask)
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
void LLScrollListCtrl::showNameDetails(std::string id, bool is_group)
|
||||
void LLScrollListCtrl::showProfile(std::string id, bool is_group)
|
||||
{
|
||||
// show the resident's profile or the group profile
|
||||
std::string sltype = is_group ? "group" : "agent";
|
||||
std::string slurl = "secondlife:///app/" + sltype + "/" + id + "/about";
|
||||
LLUrlAction::showProfile(slurl);
|
||||
}
|
||||
|
||||
void LLScrollListCtrl::sendIM(std::string id)
|
||||
{
|
||||
// send im to the resident
|
||||
std::string slurl = "secondlife:///app/agent/" + id + "/about";
|
||||
LLUrlAction::sendIM(slurl);
|
||||
}
|
||||
|
||||
void LLScrollListCtrl::addFriend(std::string id)
|
||||
{
|
||||
// add resident to friends list
|
||||
std::string slurl = "secondlife:///app/agent/" + id + "/about";
|
||||
LLUrlAction::addFriend(slurl);
|
||||
}
|
||||
|
||||
void LLScrollListCtrl::showNameDetails(std::string id, bool is_group)
|
||||
{
|
||||
// open the resident's details or the group details
|
||||
std::string sltype = is_group ? "group" : "agent";
|
||||
std::string slurl = "secondlife:///app/" + sltype + "/" + id + "/about";
|
||||
LLUrlAction::clickAction(slurl);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -430,6 +430,9 @@ private:
|
|||
BOOL setSort(S32 column, BOOL ascending);
|
||||
S32 getLinesPerPage();
|
||||
|
||||
static void showProfile(std::string id, bool is_group);
|
||||
static void sendIM(std::string id);
|
||||
static void addFriend(std::string id);
|
||||
static void showNameDetails(std::string id, bool is_group);
|
||||
static void copyNameToClipboard(std::string id, bool is_group);
|
||||
static void copySLURLToClipboard(std::string id, bool is_group);
|
||||
|
|
|
|||
|
|
@ -3201,7 +3201,23 @@ S32 LLNormalTextSegment::getNumChars(S32 num_pixels, S32 segment_offset, S32 lin
|
|||
LLFontGL::EWordWrapStyle word_wrap_style = (line_offset == 0)
|
||||
? LLFontGL::WORD_BOUNDARY_IF_POSSIBLE
|
||||
: LLFontGL::ONLY_WORD_BOUNDARIES;
|
||||
S32 num_chars = mStyle->getFont()->maxDrawableChars(text.c_str() + segment_offset + mStart,
|
||||
|
||||
|
||||
LLWString offsetString(text.c_str() + segment_offset + mStart);
|
||||
|
||||
if(getLength() < segment_offset + mStart)
|
||||
{
|
||||
llerrs << "getLength() < segment_offset + mStart\t getLength()\t" << getLength() << "\tsegment_offset:\t"
|
||||
<< segment_offset << "\tmStart:\t" << mStart << "\tsegments\t" << mEditor.mSegments.size() << "\tmax_chars\t" << max_chars << llendl;
|
||||
}
|
||||
|
||||
if(offsetString.length() + 1 < max_chars)
|
||||
{
|
||||
llerrs << "offsetString.length() + 1 < max_chars\t max_chars:\t" << max_chars << "\toffsetString.length():\t" << offsetString.length()
|
||||
<< getLength() << "\tsegment_offset:\t" << segment_offset << "\tmStart:\t" << mStart << "\tsegments\t" << mEditor.mSegments.size() << llendl;
|
||||
}
|
||||
|
||||
S32 num_chars = mStyle->getFont()->maxDrawableChars(offsetString.c_str(),
|
||||
(F32)num_pixels,
|
||||
max_chars,
|
||||
word_wrap_style);
|
||||
|
|
|
|||
|
|
@ -292,6 +292,17 @@
|
|||
<key>Value</key>
|
||||
<integer>1</integer>
|
||||
</map>
|
||||
<key>NearbyChatIsNotCollapsed</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Saving expanded/collapsed state of the nearby chat between sessions</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>Boolean</string>
|
||||
<key>Value</key>
|
||||
<integer>0</integer>
|
||||
</map>
|
||||
<key>ShowFavoritesOnLogin</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
|
|
|
|||
|
|
@ -174,6 +174,7 @@ void LLNotificationChiclet::onMenuItemClicked(const LLSD& user_data)
|
|||
if("close all" == action)
|
||||
{
|
||||
LLNotificationWellWindow::getInstance()->closeAll();
|
||||
LLIMWellWindow::getInstance()->closeAll();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -132,6 +132,8 @@ void LLDoNotDisturbNotificationStorage::loadNotifications()
|
|||
{
|
||||
LLFastTimer _(FTM_LOAD_DND_NOTIFICATIONS);
|
||||
|
||||
LL_INFOS("LLDoNotDisturbNotificationStorage") << "start loading notifications" << LL_ENDL;
|
||||
|
||||
LLSD input;
|
||||
if (!readNotifications(input) ||input.isUndefined())
|
||||
{
|
||||
|
|
@ -225,6 +227,8 @@ void LLDoNotDisturbNotificationStorage::loadNotifications()
|
|||
|
||||
//writes out empty .xml file (since LLCommunicationChannel::mHistory is empty)
|
||||
saveNotifications();
|
||||
|
||||
LL_INFOS("LLDoNotDisturbNotificationStorage") << "finished loading notifications" << LL_ENDL;
|
||||
}
|
||||
|
||||
void LLDoNotDisturbNotificationStorage::updateNotifications()
|
||||
|
|
|
|||
|
|
@ -626,6 +626,12 @@ void LLFloaterIMContainer::setVisible(BOOL visible)
|
|||
LLMultiFloater::setVisible(visible);
|
||||
}
|
||||
|
||||
void LLFloaterIMContainer::setVisibleAndFrontmost(BOOL take_focus, const LLSD& key)
|
||||
{
|
||||
LLMultiFloater::setVisibleAndFrontmost(take_focus, key);
|
||||
selectConversationPair(getSelectedSession(), false, take_focus);
|
||||
}
|
||||
|
||||
void LLFloaterIMContainer::updateResizeLimits()
|
||||
{
|
||||
LLMultiFloater::updateResizeLimits();
|
||||
|
|
@ -1331,7 +1337,10 @@ void LLFloaterIMContainer::showConversation(const LLUUID& session_id)
|
|||
selectConversationPair(session_id, true);
|
||||
|
||||
LLFloaterIMSessionTab* session_floater = LLFloaterIMSessionTab::findConversation(session_id);
|
||||
session_floater->restoreFloater();
|
||||
if (session_floater)
|
||||
{
|
||||
session_floater->restoreFloater();
|
||||
}
|
||||
}
|
||||
|
||||
void LLFloaterIMContainer::clearAllFlashStates()
|
||||
|
|
@ -1963,10 +1972,13 @@ bool LLFloaterIMContainer::selectNextorPreviousConversation(bool select_next, bo
|
|||
|
||||
void LLFloaterIMContainer::expandConversation()
|
||||
{
|
||||
LLConversationViewSession* widget = dynamic_cast<LLConversationViewSession*>(get_ptr_in_map(mConversationsWidgets,getSelectedSession()));
|
||||
if (widget)
|
||||
if(!mConversationsPane->isCollapsed())
|
||||
{
|
||||
widget->setOpen(!widget->isOpen());
|
||||
LLConversationViewSession* widget = dynamic_cast<LLConversationViewSession*>(get_ptr_in_map(mConversationsWidgets,getSelectedSession()));
|
||||
if (widget)
|
||||
{
|
||||
widget->setOpen(!widget->isOpen());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -60,6 +60,7 @@ public:
|
|||
/*virtual*/ void onOpen(const LLSD& key);
|
||||
/*virtual*/ void draw();
|
||||
/*virtual*/ void setVisible(BOOL visible);
|
||||
/*virtual*/ void setVisibleAndFrontmost(BOOL take_focus=TRUE, const LLSD& key = LLSD());
|
||||
/*virtual*/ void updateResizeLimits();
|
||||
void onCloseFloater(LLUUID& id);
|
||||
|
||||
|
|
|
|||
|
|
@ -283,6 +283,11 @@ void LLFloaterIMNearbyChat::onTearOffClicked()
|
|||
void LLFloaterIMNearbyChat::onOpen(const LLSD& key)
|
||||
{
|
||||
LLFloaterIMSessionTab::onOpen(key);
|
||||
if(!isMessagePaneExpanded())
|
||||
{
|
||||
restoreFloater();
|
||||
onCollapseToLine(this);
|
||||
}
|
||||
showTranslationCheckbox(LLTranslate::isTranslationConfigured());
|
||||
}
|
||||
|
||||
|
|
@ -322,11 +327,8 @@ void LLFloaterIMNearbyChat::onChatFontChange(LLFontGL* fontp)
|
|||
|
||||
void LLFloaterIMNearbyChat::show()
|
||||
{
|
||||
if (isChatMultiTab())
|
||||
{
|
||||
openFloater(getKey());
|
||||
}
|
||||
}
|
||||
|
||||
bool LLFloaterIMNearbyChat::isChatVisible() const
|
||||
{
|
||||
|
|
@ -480,11 +482,14 @@ void LLFloaterIMNearbyChat::onChatBoxKeystroke()
|
|||
if (LLGestureMgr::instance().matchPrefix(utf8_trigger, &utf8_out_str))
|
||||
{
|
||||
std::string rest_of_match = utf8_out_str.substr(utf8_trigger.size());
|
||||
mInputEditor->setText(utf8_trigger + rest_of_match); // keep original capitalization for user-entered part
|
||||
if (!rest_of_match.empty())
|
||||
{
|
||||
mInputEditor->setText(utf8_trigger + rest_of_match); // keep original capitalization for user-entered part
|
||||
|
||||
// Select to end of line, starting from the character
|
||||
// after the last one the user typed.
|
||||
mInputEditor->selectNext(rest_of_match, false);
|
||||
// Select to end of line, starting from the character
|
||||
// after the last one the user typed.
|
||||
mInputEditor->selectNext(rest_of_match, false);
|
||||
}
|
||||
}
|
||||
else if (matchChatTypeTrigger(utf8_trigger, &utf8_out_str))
|
||||
{
|
||||
|
|
@ -741,15 +746,14 @@ void LLFloaterIMNearbyChat::startChat(const char* line)
|
|||
{
|
||||
if(!nearby_chat->isTornOff())
|
||||
{
|
||||
nearby_chat->show();
|
||||
LLFloaterIMContainer::getInstance()->selectConversation(LLUUID(NULL));
|
||||
}
|
||||
if(nearby_chat->isMinimized())
|
||||
{
|
||||
nearby_chat->setMinimized(false);
|
||||
}
|
||||
nearby_chat->setVisible(TRUE);
|
||||
nearby_chat->show();
|
||||
nearby_chat->setFocus(TRUE);
|
||||
nearby_chat->mInputEditor->setFocus(TRUE);
|
||||
|
||||
if (line)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -559,9 +559,7 @@ void LLFloaterIMNearbyChatHandler::processChat(const LLChat& chat_msg,
|
|||
|
||||
LLFloaterIMContainer* im_box = LLFloaterReg::getTypedInstance<LLFloaterIMContainer>("im_container");
|
||||
|
||||
if(( nearby_chat->hasFocus()
|
||||
|| im_box->hasFocus()
|
||||
|| ( chat_msg.mSourceType == CHAT_SOURCE_AGENT
|
||||
if(( ( chat_msg.mSourceType == CHAT_SOURCE_AGENT
|
||||
&& gSavedSettings.getBOOL("UseChatBubbles") )
|
||||
|| mChannel.isDead()
|
||||
|| !mChannel.get()->getShowToasts() )
|
||||
|
|
@ -606,17 +604,16 @@ void LLFloaterIMNearbyChatHandler::processChat(const LLChat& chat_msg,
|
|||
toast_msg = chat_msg.mText;
|
||||
}
|
||||
|
||||
//Don't show nearby toast, if conversation is visible but not focused
|
||||
LLFloaterIMSessionTab* session_floater = LLFloaterIMSessionTab::getConversation(LLUUID());
|
||||
if (session_floater && session_floater->isMessagePaneExpanded()
|
||||
&& session_floater->isInVisibleChain() && !session_floater->isMinimized()
|
||||
&& !(session_floater->getHost() && session_floater->getHost()->isMinimized()))
|
||||
//Don't show nearby toast, if conversation is visible and selected
|
||||
if (im_box->getSelectedSession().isNull() &&
|
||||
((LLFloater::isVisible(im_box) && !im_box->isMinimized() && im_box->isFrontmost())
|
||||
|| (LLFloater::isVisible(nearby_chat) && !nearby_chat->isMinimized() && nearby_chat->isFrontmost())))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
//Will show toast when chat preference is set
|
||||
if((gSavedSettings.getString("NotificationNearbyChatOptions") == "toast") || !session_floater->isMessagePaneExpanded())
|
||||
if((gSavedSettings.getString("NotificationNearbyChatOptions") == "toast") || !nearby_chat->isMessagePaneExpanded())
|
||||
{
|
||||
// Add a nearby chat toast.
|
||||
LLUUID id;
|
||||
|
|
|
|||
|
|
@ -618,6 +618,8 @@ void LLFloaterIMSession::onClose(bool app_quitting)
|
|||
// Last change:
|
||||
// EXT-3516 X Button should end IM session, _ button should hide
|
||||
gIMMgr->leaveSession(mSessionID);
|
||||
// *TODO: Study why we need to restore the floater before we close it.
|
||||
// Might be because we want to save some state data in some clean open state.
|
||||
LLFloaterIMSessionTab::restoreFloater();
|
||||
// Clean up the conversation *after* the session has been ended
|
||||
LLFloaterIMSessionTab::onClose(app_quitting);
|
||||
|
|
|
|||
|
|
@ -132,6 +132,12 @@ void LLFloaterIMSessionTab::setVisible(BOOL visible)
|
|||
LLFloaterReg::getTypedInstance<LLFloaterIMContainer>("im_container")->setVisible(true);
|
||||
}
|
||||
LLFloaterIMSessionTab::addToHost(mSessionID);
|
||||
LLFloaterIMSessionTab* conversp = LLFloaterIMSessionTab::getConversation(mSessionID);
|
||||
|
||||
if (conversp && conversp->isNearbyChat() && gSavedPerAccountSettings.getBOOL("NearbyChatIsNotCollapsed"))
|
||||
{
|
||||
onCollapseToLine(this);
|
||||
}
|
||||
mInputButtonPanel->setVisible(isTornOff());
|
||||
}
|
||||
|
||||
|
|
@ -356,7 +362,7 @@ void LLFloaterIMSessionTab::draw()
|
|||
// Restart the refresh timer
|
||||
mRefreshTimer->setTimerExpirySec(REFRESH_INTERVAL);
|
||||
}
|
||||
|
||||
|
||||
LLTransientDockableFloater::draw();
|
||||
}
|
||||
|
||||
|
|
@ -698,10 +704,12 @@ void LLFloaterIMSessionTab::updateHeaderAndToolbar()
|
|||
&& !mIsP2PChat;
|
||||
|
||||
mParticipantListAndHistoryStack->collapsePanel(mParticipantListPanel, !is_participant_list_visible);
|
||||
mParticipantListPanel->setVisible(is_participant_list_visible);
|
||||
|
||||
// Display collapse image (<<) if the floater is hosted
|
||||
// or if it is torn off but has an open control panel.
|
||||
bool is_expanded = is_not_torn_off || is_participant_list_visible;
|
||||
|
||||
mExpandCollapseBtn->setImageOverlay(getString(is_expanded ? "collapse_icon" : "expand_icon"));
|
||||
mExpandCollapseBtn->setToolTip(
|
||||
is_not_torn_off?
|
||||
|
|
@ -818,14 +826,15 @@ void LLFloaterIMSessionTab::onSlide(LLFloaterIMSessionTab* self)
|
|||
{
|
||||
if (!self->mIsP2PChat)
|
||||
{
|
||||
// The state must toggle the collapsed state of the panel
|
||||
bool should_be_expanded = self->mParticipantListPanel->isCollapsed();
|
||||
|
||||
// Expand/collapse the participant list panel
|
||||
self->mParticipantListAndHistoryStack->collapsePanel(self->mParticipantListPanel, !should_be_expanded);
|
||||
self->mParticipantListPanel->setVisible(should_be_expanded);
|
||||
// Update the expand/collapse flag of the participant list panel and save it
|
||||
gSavedSettings.setBOOL("IMShowControlPanel", should_be_expanded);
|
||||
self->mIsParticipantListExpanded = should_be_expanded;
|
||||
self->mExpandCollapseBtn->setImageOverlay(self->getString(should_be_expanded ? "collapse_icon" : "expand_icon"));
|
||||
|
||||
// Refresh for immediate feedback
|
||||
self->refreshConversation();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -863,7 +872,7 @@ void LLFloaterIMSessionTab::reshapeFloater(bool collapse)
|
|||
enableResizeCtrls(true, true, true);
|
||||
|
||||
}
|
||||
|
||||
saveCollapsedState();
|
||||
setShape(floater_rect, true);
|
||||
mBodyStack->updateLayout();
|
||||
|
||||
|
|
@ -885,6 +894,7 @@ void LLFloaterIMSessionTab::restoreFloater()
|
|||
mBodyStack->updateLayout();
|
||||
mExpandCollapseLineBtn->setImageOverlay(getString("expandline_icon"));
|
||||
setMessagePaneExpanded(true);
|
||||
saveCollapsedState();
|
||||
enableResizeCtrls(true, true, true);
|
||||
}
|
||||
}
|
||||
|
|
@ -1060,6 +1070,14 @@ LLConversationItem* LLFloaterIMSessionTab::getCurSelectedViewModelItem()
|
|||
return conversationItem;
|
||||
}
|
||||
|
||||
void LLFloaterIMSessionTab::saveCollapsedState()
|
||||
{
|
||||
LLFloaterIMSessionTab* conversp = LLFloaterIMSessionTab::getConversation(mSessionID);
|
||||
if(conversp->isNearbyChat())
|
||||
{
|
||||
gSavedPerAccountSettings.setBOOL("NearbyChatIsNotCollapsed", isMessagePaneExpanded());
|
||||
}
|
||||
}
|
||||
BOOL LLFloaterIMSessionTab::handleKeyHere(KEY key, MASK mask )
|
||||
{
|
||||
if(mask == MASK_ALT)
|
||||
|
|
|
|||
|
|
@ -101,6 +101,7 @@ public:
|
|||
bool isMessagePaneExpanded(){return mMessagePaneExpanded;}
|
||||
void setMessagePaneExpanded(bool expanded){mMessagePaneExpanded = expanded;}
|
||||
void restoreFloater();
|
||||
void saveCollapsedState();
|
||||
|
||||
protected:
|
||||
|
||||
|
|
|
|||
|
|
@ -160,163 +160,150 @@ static void on_avatar_name_cache_toast(const LLUUID& agent_id,
|
|||
|
||||
void on_new_message(const LLSD& msg)
|
||||
{
|
||||
std::string action;
|
||||
std::string user_preferences;
|
||||
LLUUID participant_id = msg["from_id"].asUUID();
|
||||
LLUUID session_id = msg["session_id"].asUUID();
|
||||
LLIMModel::LLIMSession* session = LLIMModel::instance().findIMSession(session_id);
|
||||
|
||||
// determine action for this session
|
||||
|
||||
if (session_id.isNull())
|
||||
{
|
||||
action = gSavedSettings.getString("NotificationNearbyChatOptions");
|
||||
}
|
||||
else if(session->isP2PSessionType())
|
||||
{
|
||||
if (LLAvatarTracker::instance().isBuddy(participant_id))
|
||||
{
|
||||
action = gSavedSettings.getString("NotificationFriendIMOptions");
|
||||
}
|
||||
else
|
||||
{
|
||||
action = gSavedSettings.getString("NotificationNonFriendIMOptions");
|
||||
}
|
||||
}
|
||||
else if(session->isAdHocSessionType())
|
||||
{
|
||||
action = gSavedSettings.getString("NotificationConferenceIMOptions");
|
||||
}
|
||||
else if(session->isGroupSessionType())
|
||||
{
|
||||
action = gSavedSettings.getString("NotificationGroupChatOptions");
|
||||
}
|
||||
|
||||
// do not show notification which goes from agent
|
||||
if (gAgent.getID() == participant_id)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// execution of the action
|
||||
// determine state of conversations floater
|
||||
enum {CLOSED, NOT_ON_TOP, ON_TOP, ON_TOP_AND_ITEM_IS_SELECTED} conversations_floater_status;
|
||||
|
||||
LLFloaterIMContainer* im_box = LLFloaterReg::getTypedInstance<LLFloaterIMContainer>("im_container");
|
||||
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()))
|
||||
|
||||
if (!LLFloater::isVisible(im_box) || im_box->isMinimized())
|
||||
{
|
||||
return;
|
||||
conversations_floater_status = CLOSED;
|
||||
}
|
||||
else if ( !im_box->hasFocus() &&
|
||||
(!session_floater || !LLFloater::isVisible(session_floater)
|
||||
|| session_floater->isMinimized() || !session_floater->hasFocus()))
|
||||
{
|
||||
conversations_floater_status = NOT_ON_TOP;
|
||||
}
|
||||
else if (im_box->getSelectedSession() != session_id)
|
||||
{
|
||||
conversations_floater_status = ON_TOP;
|
||||
}
|
||||
else
|
||||
{
|
||||
conversations_floater_status = ON_TOP_AND_ITEM_IS_SELECTED;
|
||||
}
|
||||
|
||||
//session floater not focused (visible or not)
|
||||
bool session_floater_not_focused = session_floater && !session_floater->hasFocus();
|
||||
|
||||
//conv. floater is closed
|
||||
bool conversation_floater_is_closed =
|
||||
!( im_box
|
||||
&& im_box->isInVisibleChain()
|
||||
&& !im_box->isMinimized());
|
||||
|
||||
//conversation floater not focused (visible or not)
|
||||
bool conversation_floater_not_focused =
|
||||
conversation_floater_is_closed || !im_box->hasFocus();
|
||||
// sess. floater is open
|
||||
bool session_floater_is_open =
|
||||
session_floater
|
||||
&& session_floater->isInVisibleChain()
|
||||
&& !session_floater->isMinimized()
|
||||
&& !(session_floater->getHost() && session_floater->getHost()->isMinimized());
|
||||
|
||||
bool conversation_floater_collapsed = !session_floater->isMessagePaneExpanded();
|
||||
if (("toast" == action && !session_floater_is_open) || conversation_floater_collapsed)
|
||||
// determine user prefs for this session
|
||||
if (session_id.isNull())
|
||||
{
|
||||
//User is not focused on conversation containing the message
|
||||
if(session_floater_not_focused || conversation_floater_collapsed)
|
||||
user_preferences = gSavedSettings.getString("NotificationNearbyChatOptions");
|
||||
}
|
||||
else if(session->isP2PSessionType())
|
||||
{
|
||||
if (LLAvatarTracker::instance().isBuddy(participant_id))
|
||||
{
|
||||
if(!LLMuteList::getInstance()->isMuted(participant_id))
|
||||
{
|
||||
im_box->flashConversationItemWidget(session_id, true);
|
||||
}
|
||||
//The conversation floater isn't focused/open
|
||||
if(conversation_floater_not_focused || conversation_floater_collapsed)
|
||||
{
|
||||
if(!LLMuteList::getInstance()->isMuted(participant_id)
|
||||
&& !gAgent.isDoNotDisturb())
|
||||
{
|
||||
gToolBarView->flashCommand(LLCommandId("chat"), true);
|
||||
}
|
||||
|
||||
//Show IM toasts (upper right toasts)
|
||||
// Skip toasting for system messages and for nearby chat
|
||||
if(session_id.notNull() && participant_id.notNull())
|
||||
{
|
||||
LLAvatarNameCache::get(participant_id, boost::bind(&on_avatar_name_cache_toast, _1, _2, msg));
|
||||
}
|
||||
}
|
||||
}
|
||||
user_preferences = gSavedSettings.getString("NotificationFriendIMOptions");
|
||||
}
|
||||
else
|
||||
{
|
||||
user_preferences = gSavedSettings.getString("NotificationNonFriendIMOptions");
|
||||
}
|
||||
}
|
||||
else if(session->isAdHocSessionType())
|
||||
{
|
||||
user_preferences = gSavedSettings.getString("NotificationConferenceIMOptions");
|
||||
}
|
||||
else if(session->isGroupSessionType())
|
||||
{
|
||||
user_preferences = gSavedSettings.getString("NotificationGroupChatOptions");
|
||||
}
|
||||
|
||||
else if ("flash" == action)
|
||||
// actions:
|
||||
|
||||
// 0. nothing - exit
|
||||
if (("none" == user_preferences ||
|
||||
ON_TOP_AND_ITEM_IS_SELECTED == conversations_floater_status)
|
||||
&& session_floater->isMessagePaneExpanded())
|
||||
{
|
||||
if (!gAgent.isDoNotDisturb())
|
||||
{
|
||||
im_box->flashConversationItemWidget(session_id, true);
|
||||
if(conversation_floater_not_focused)
|
||||
return;
|
||||
}
|
||||
|
||||
// 1. open floater and [optional] surface it
|
||||
if ("openconversations" == user_preferences &&
|
||||
(CLOSED == conversations_floater_status
|
||||
|| NOT_ON_TOP == conversations_floater_status))
|
||||
{
|
||||
if(!gAgent.isDoNotDisturb())
|
||||
{
|
||||
// Open conversations floater
|
||||
LLFloaterReg::showInstance("im_container");
|
||||
im_box->collapseMessagesPane(false);
|
||||
if (session_floater)
|
||||
{
|
||||
//User is not focused on conversation containing the message
|
||||
gToolBarView->flashCommand(LLCommandId("chat"), true);
|
||||
}
|
||||
}
|
||||
else if(session_id.notNull() && participant_id.notNull())
|
||||
{
|
||||
//If a DND message, allow notification to be stored so upon DND exit
|
||||
//useMostItrusiveIMNotification will be called to notify user a message exists
|
||||
LLAvatarNameCache::get(participant_id, boost::bind(&on_avatar_name_cache_toast, _1, _2, msg));
|
||||
}
|
||||
}
|
||||
|
||||
else if("openconversations" == action)
|
||||
{
|
||||
//User is not focused on conversation containing the message
|
||||
if(session_floater_not_focused)
|
||||
{
|
||||
//Flash line item
|
||||
im_box->flashConversationItemWidget(session_id, true);
|
||||
|
||||
if(!gAgent.isDoNotDisturb())
|
||||
{
|
||||
//Surface conversations floater
|
||||
LLFloaterReg::showInstance("im_container");
|
||||
im_box->collapseMessagesPane(false);
|
||||
if (session_floater)
|
||||
if (session_floater->getHost())
|
||||
{
|
||||
if (session_floater->getHost())
|
||||
if (NULL != im_box && im_box->isMinimized())
|
||||
{
|
||||
if (NULL != im_box && im_box->isMinimized())
|
||||
{
|
||||
LLFloater::onClickMinimize(im_box);
|
||||
}
|
||||
LLFloater::onClickMinimize(im_box);
|
||||
}
|
||||
else
|
||||
}
|
||||
else
|
||||
{
|
||||
if (session_floater->isMinimized())
|
||||
{
|
||||
if (session_floater->isMinimized())
|
||||
{
|
||||
LLFloater::onClickMinimize(session_floater);
|
||||
}
|
||||
LLFloater::onClickMinimize(session_floater);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//If in DND mode, allow notification to be stored so upon DND exit
|
||||
}
|
||||
else
|
||||
{
|
||||
//If in DND mode, allow notification to be stored so upon DND exit
|
||||
//useMostItrusiveIMNotification will be called to notify user a message exists
|
||||
if(session_id.notNull()
|
||||
&& participant_id.notNull()
|
||||
&& gAgent.isDoNotDisturb()
|
||||
&& !session_floater_is_open)
|
||||
if(session_id.notNull()
|
||||
&& participant_id.notNull()
|
||||
&& !session_floater->isShown())
|
||||
{
|
||||
LLAvatarNameCache::get(participant_id, boost::bind(&on_avatar_name_cache_toast, _1, _2, msg));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 2. Flash line item
|
||||
if ("openconversations" == user_preferences
|
||||
|| ON_TOP == conversations_floater_status)
|
||||
{
|
||||
if(!LLMuteList::getInstance()->isMuted(participant_id))
|
||||
{
|
||||
im_box->flashConversationItemWidget(session_id, true);
|
||||
}
|
||||
}
|
||||
|
||||
// 3. Flash FUI button
|
||||
if (("toast" == user_preferences || "flash" == user_preferences) &&
|
||||
(CLOSED == conversations_floater_status
|
||||
|| NOT_ON_TOP == conversations_floater_status))
|
||||
{
|
||||
if(!LLMuteList::getInstance()->isMuted(participant_id)
|
||||
&& !gAgent.isDoNotDisturb())
|
||||
{
|
||||
gToolBarView->flashCommand(LLCommandId("chat"), true);
|
||||
}
|
||||
}
|
||||
|
||||
// 4. Toast
|
||||
if ("toast" == user_preferences
|
||||
|| !session_floater->isMessagePaneExpanded())
|
||||
{
|
||||
//Show IM toasts (upper right toasts)
|
||||
// Skip toasting for system messages and for nearby chat
|
||||
if(session_id.notNull() && participant_id.notNull())
|
||||
{
|
||||
LLAvatarNameCache::get(participant_id, boost::bind(&on_avatar_name_cache_toast, _1, _2, msg));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -105,6 +105,8 @@ bool LLNotificationStorage::writeNotifications(const LLSD& pNotificationData) co
|
|||
|
||||
bool LLNotificationStorage::readNotifications(LLSD& pNotificationData) const
|
||||
{
|
||||
LL_INFOS("LLNotificationStorage") << "starting read '" << mFileName << "'" << LL_ENDL;
|
||||
|
||||
bool didFileRead;
|
||||
|
||||
pNotificationData.clear();
|
||||
|
|
@ -126,6 +128,8 @@ bool LLNotificationStorage::readNotifications(LLSD& pNotificationData) const
|
|||
}
|
||||
}
|
||||
|
||||
LL_INFOS("LLNotificationStorage") << "ending read '" << mFileName << "'" << LL_ENDL;
|
||||
|
||||
return didFileRead;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -87,6 +87,8 @@ void LLPersistentNotificationStorage::loadNotifications()
|
|||
{
|
||||
LLFastTimer _(FTM_LOAD_NOTIFICATIONS);
|
||||
|
||||
LL_INFOS("LLPersistentNotificationStorage") << "start loading notifications" << LL_ENDL;
|
||||
|
||||
LLNotifications::instance().getChannel("Persistent")->
|
||||
connectChanged(boost::bind(&LLPersistentNotificationStorage::onPersistentChannelChanged, this, _1));
|
||||
|
||||
|
|
@ -129,6 +131,8 @@ void LLPersistentNotificationStorage::loadNotifications()
|
|||
notification_channel->hideToast(notification->getID());
|
||||
}
|
||||
}
|
||||
|
||||
LL_INFOS("LLPersistentNotificationStorage") << "finished loading notifications" << LL_ENDL;
|
||||
}
|
||||
|
||||
bool LLPersistentNotificationStorage::onPersistentChannelChanged(const LLSD& payload)
|
||||
|
|
|
|||
|
|
@ -675,7 +675,7 @@ LLVOAvatar::LLVOAvatar(const LLUUID& id,
|
|||
mBelowWater(FALSE),
|
||||
mLastAppearanceBlendTime(0.f),
|
||||
mAppearanceAnimating(FALSE),
|
||||
mNameString(),
|
||||
mNameIsSet(false),
|
||||
mTitle(),
|
||||
mNameAway(false),
|
||||
mNameDoNotDisturb(false),
|
||||
|
|
@ -3096,8 +3096,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 ""
|
||||
if (!mNameIsSet
|
||||
|| new_name
|
||||
|| (!title && !mTitle.empty())
|
||||
|| (title && mTitle != title->getString())
|
||||
|
|
@ -3292,17 +3291,16 @@ void LLVOAvatar::addNameTagLine(const std::string& line, const LLColor4& color,
|
|||
{
|
||||
mNameText->addLine(line, color, (LLFontGL::StyleFlags)style, font);
|
||||
}
|
||||
mNameString += line;
|
||||
mNameString += '\n';
|
||||
mNameIsSet |= !line.empty();
|
||||
}
|
||||
|
||||
void LLVOAvatar::clearNameTag()
|
||||
{
|
||||
mNameString.clear();
|
||||
mNameIsSet = false;
|
||||
if (mNameText)
|
||||
{
|
||||
mNameText->setLabel("");
|
||||
mNameText->setString( "" );
|
||||
mNameText->setString("");
|
||||
}
|
||||
mTimeVisible.reset();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -939,7 +939,7 @@ protected:
|
|||
static void getAnimLabels(LLDynamicArray<std::string>* labels);
|
||||
static void getAnimNames(LLDynamicArray<std::string>* names);
|
||||
private:
|
||||
std::string mNameString; // UTF-8 title + name + status
|
||||
bool mNameIsSet;
|
||||
std::string mTitle;
|
||||
bool mNameAway;
|
||||
bool mNameDoNotDisturb;
|
||||
|
|
|
|||
|
|
@ -1258,7 +1258,7 @@ void LLVivoxVoiceClient::stateMachine()
|
|||
|
||||
//MARK: stateCreatingSessionGroup
|
||||
case stateCreatingSessionGroup:
|
||||
if(mSessionTerminateRequested || !mVoiceEnabled && mIsInitialized)
|
||||
if(mSessionTerminateRequested || (!mVoiceEnabled && mIsInitialized))
|
||||
{
|
||||
// *TODO: Question: is this the right way out of this state
|
||||
setState(stateSessionTerminated);
|
||||
|
|
@ -1274,7 +1274,7 @@ void LLVivoxVoiceClient::stateMachine()
|
|||
//MARK: stateRetrievingParcelVoiceInfo
|
||||
case stateRetrievingParcelVoiceInfo:
|
||||
// wait until parcel voice info is received.
|
||||
if(mSessionTerminateRequested || !mVoiceEnabled && mIsInitialized)
|
||||
if(mSessionTerminateRequested || (!mVoiceEnabled && mIsInitialized))
|
||||
{
|
||||
// if a terminate request has been received,
|
||||
// bail and go to the stateSessionTerminated
|
||||
|
|
@ -1294,7 +1294,7 @@ void LLVivoxVoiceClient::stateMachine()
|
|||
// Otherwise, if you log in but don't join a proximal channel (such as when your login location has voice disabled), your friends list won't sync.
|
||||
sendFriendsListUpdates();
|
||||
|
||||
if(mSessionTerminateRequested || !mVoiceEnabled && mIsInitialized)
|
||||
if(mSessionTerminateRequested || (!mVoiceEnabled && mIsInitialized))
|
||||
{
|
||||
// TODO: Question: Is this the right way out of this state?
|
||||
setState(stateSessionTerminated);
|
||||
|
|
@ -1442,7 +1442,7 @@ void LLVivoxVoiceClient::stateMachine()
|
|||
//MARK: stateRunning
|
||||
case stateRunning: // steady state
|
||||
// Disabling voice or disconnect requested.
|
||||
if(!mVoiceEnabled && mIsInitialized || mSessionTerminateRequested)
|
||||
if((!mVoiceEnabled && mIsInitialized) || mSessionTerminateRequested)
|
||||
{
|
||||
leaveAudioSession();
|
||||
}
|
||||
|
|
@ -2671,33 +2671,19 @@ void LLVivoxVoiceClient::checkFriend(const LLUUID& id)
|
|||
{
|
||||
buddyListEntry *buddy = findBuddy(id);
|
||||
|
||||
// Make sure we don't add a name before it's been looked up.
|
||||
// Make sure we don't add a name before it's been looked up in the avatar name cache
|
||||
LLAvatarName av_name;
|
||||
if(LLAvatarNameCache::get(id, &av_name))
|
||||
if (LLAvatarNameCache::get(id, &av_name))
|
||||
{
|
||||
// *NOTE: For now, we feed legacy names to Vivox because I don't know
|
||||
// if their service can support a mix of new and old clients with
|
||||
// different sorts of names.
|
||||
// *NOTE: We feed legacy names to Vivox because we don't know if their service
|
||||
// can support a mix of new and old clients with different sorts of names.
|
||||
std::string name = av_name.getAccountName();
|
||||
|
||||
const LLRelationship* relationInfo = LLAvatarTracker::instance().getBuddyInfo(id);
|
||||
bool canSeeMeOnline = false;
|
||||
if(relationInfo && relationInfo->isRightGrantedTo(LLRelationship::GRANT_ONLINE_STATUS))
|
||||
canSeeMeOnline = true;
|
||||
|
||||
// When we get here, mNeedsSend is true and mInSLFriends is false. Change them as necessary.
|
||||
|
||||
if(buddy)
|
||||
if (buddy)
|
||||
{
|
||||
// This buddy is already in both lists.
|
||||
|
||||
if(name != buddy->mDisplayName)
|
||||
{
|
||||
// The buddy is in the list with the wrong name. Update it with the correct name.
|
||||
LL_WARNS("Voice") << "Buddy " << id << " has wrong name (\"" << buddy->mDisplayName << "\" should be \"" << name << "\"), updating."<< LL_ENDL;
|
||||
buddy->mDisplayName = name;
|
||||
buddy->mNeedsNameUpdate = true; // This will cause the buddy to be resent.
|
||||
}
|
||||
// This buddy is already in both lists (vivox buddies and avatar cache).
|
||||
// Trust the avatar cache more for the display name (vivox display name are notoriously wrong)
|
||||
buddy->mDisplayName = name;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -2706,20 +2692,19 @@ void LLVivoxVoiceClient::checkFriend(const LLUUID& id)
|
|||
buddy->mUUID = id;
|
||||
}
|
||||
|
||||
// In all the above cases, the buddy is in the SL friends list (which is how we got here).
|
||||
buddy->mInSLFriends = true;
|
||||
buddy->mCanSeeMeOnline = canSeeMeOnline;
|
||||
const LLRelationship* relationInfo = LLAvatarTracker::instance().getBuddyInfo(id);
|
||||
buddy->mCanSeeMeOnline = (relationInfo && relationInfo->isRightGrantedTo(LLRelationship::GRANT_ONLINE_STATUS));
|
||||
// In all the above cases, the buddy is in the SL friends list and tha name has been resolved (which is how we got here).
|
||||
buddy->mNameResolved = true;
|
||||
|
||||
buddy->mInSLFriends = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// This name hasn't been looked up yet. Don't do anything with this buddy list entry until it has.
|
||||
if(buddy)
|
||||
// This name hasn't been looked up yet in the avatar cache. Don't do anything with this buddy list entry until it has.
|
||||
if (buddy)
|
||||
{
|
||||
buddy->mNameResolved = false;
|
||||
}
|
||||
|
||||
// Initiate a lookup.
|
||||
// The "lookup completed" callback will ensure that the friends list is rechecked after it completes.
|
||||
lookupName(id);
|
||||
|
|
@ -2827,13 +2812,12 @@ void LLVivoxVoiceClient::sendFriendsListUpdates()
|
|||
{
|
||||
std::ostringstream stream;
|
||||
|
||||
if(buddy->mInSLFriends && (!buddy->mInVivoxBuddies || buddy->mNeedsNameUpdate))
|
||||
if(buddy->mInSLFriends && !buddy->mInVivoxBuddies)
|
||||
{
|
||||
if(mNumberOfAliases > 0)
|
||||
{
|
||||
// Add (or update) this entry in the vivox buddy list
|
||||
buddy->mInVivoxBuddies = true;
|
||||
buddy->mNeedsNameUpdate = false;
|
||||
LL_DEBUGS("Voice") << "add/update " << buddy->mURI << " (" << buddy->mDisplayName << ")" << LL_ENDL;
|
||||
stream
|
||||
<< "<Request requestId=\"" << mCommandCookie++ << "\" action=\"Account.BuddySet.1\">"
|
||||
|
|
@ -5859,7 +5843,6 @@ LLVivoxVoiceClient::buddyListEntry::buddyListEntry(const std::string &uri) :
|
|||
mNameResolved = false;
|
||||
mInVivoxBuddies = false;
|
||||
mInSLFriends = false;
|
||||
mNeedsNameUpdate = false;
|
||||
}
|
||||
|
||||
void LLVivoxVoiceClient::processBuddyListEntry(const std::string &uri, const std::string &displayName)
|
||||
|
|
@ -5884,25 +5867,21 @@ LLVivoxVoiceClient::buddyListEntry *LLVivoxVoiceClient::addBuddy(const std::stri
|
|||
buddyListEntry *result = NULL;
|
||||
buddyListMap::iterator iter = mBuddyListMap.find(uri);
|
||||
|
||||
if(iter != mBuddyListMap.end())
|
||||
if (iter != mBuddyListMap.end())
|
||||
{
|
||||
// Found a matching buddy already in the map.
|
||||
LL_DEBUGS("Voice") << "adding existing buddy " << uri << LL_ENDL;
|
||||
result = iter->second;
|
||||
}
|
||||
|
||||
if(!result)
|
||||
if (!result)
|
||||
{
|
||||
// participant isn't already in one list or the other.
|
||||
LL_DEBUGS("Voice") << "adding new buddy " << uri << LL_ENDL;
|
||||
result = new buddyListEntry(uri);
|
||||
result->mDisplayName = displayName;
|
||||
|
||||
if(IDFromName(uri, result->mUUID))
|
||||
{
|
||||
// Extracted UUID from name successfully.
|
||||
}
|
||||
else
|
||||
if (!IDFromName(uri, result->mUUID))
|
||||
{
|
||||
LL_DEBUGS("Voice") << "Couldn't find ID for buddy " << uri << " (\"" << displayName << "\")" << LL_ENDL;
|
||||
}
|
||||
|
|
@ -7272,7 +7251,7 @@ void LLVivoxProtocolParser::StartTag(const char *tag, const char **attr)
|
|||
void LLVivoxProtocolParser::EndTag(const char *tag)
|
||||
{
|
||||
const std::string& string = textBuffer;
|
||||
|
||||
|
||||
responseDepth--;
|
||||
|
||||
if (ignoringTags)
|
||||
|
|
@ -7371,6 +7350,8 @@ void LLVivoxProtocolParser::EndTag(const char *tag)
|
|||
}
|
||||
else if (!stricmp("Buddy", tag))
|
||||
{
|
||||
// NOTE : Vivox does *not* give reliable display name for Buddy tags
|
||||
// We don't take those very seriously as a result...
|
||||
LLVivoxVoiceClient::getInstance()->processBuddyListEntry(uriString, displayNameString);
|
||||
}
|
||||
else if (!stricmp("BlockRule", tag))
|
||||
|
|
|
|||
|
|
@ -584,7 +584,6 @@ protected:
|
|||
bool mNameResolved;
|
||||
bool mInSLFriends;
|
||||
bool mInVivoxBuddies;
|
||||
bool mNeedsNameUpdate;
|
||||
};
|
||||
|
||||
typedef std::map<std::string, buddyListEntry*> buddyListMap;
|
||||
|
|
|
|||
Loading…
Reference in New Issue