diff options
| -rw-r--r-- | indra/llui/llfloater.cpp | 7 | ||||
| -rwxr-xr-x | indra/newview/app_settings/settings.xml | 2 | ||||
| -rwxr-xr-x | indra/newview/llagent.cpp | 2 | ||||
| -rw-r--r-- | indra/newview/llcommunicationchannel.cpp | 36 | ||||
| -rw-r--r-- | indra/newview/llcommunicationchannel.h | 7 | ||||
| -rw-r--r-- | indra/newview/lldonotdisturbnotificationstorage.cpp | 150 | ||||
| -rw-r--r-- | indra/newview/lldonotdisturbnotificationstorage.h | 22 | ||||
| -rw-r--r-- | indra/newview/llfloaterimcontainer.cpp | 10 | ||||
| -rw-r--r-- | indra/newview/llimview.cpp | 45 | ||||
| -rw-r--r-- | indra/newview/llpanelblockedlist.cpp | 3 | ||||
| -rw-r--r-- | indra/newview/lltoastnotifypanel.cpp | 15 | 
11 files changed, 253 insertions, 46 deletions
| diff --git a/indra/llui/llfloater.cpp b/indra/llui/llfloater.cpp index 8f9be5285d..d2aae11191 100644 --- a/indra/llui/llfloater.cpp +++ b/indra/llui/llfloater.cpp @@ -655,7 +655,7 @@ void LLFloater::openFloater(const LLSD& key)  {  	llinfos << "Opening floater " << getName() << llendl;  	mKey = key; // in case we need to open ourselves again -	 +  	if (getSoundFlags() != SILENT   	// don't play open sound for hosted (tabbed) windows  		&& !getHost()  @@ -2394,6 +2394,11 @@ void LLFloaterView::bringToFront(LLFloater* child, BOOL give_focus)  {  	if (mFrontChild == child)  	{ + +		if (give_focus && !gFocusMgr.childHasKeyboardFocus(child)) +		{ +			child->setFocus(TRUE); +		}  		return;  	} diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 126df69519..fd4d1df894 100755 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -10215,7 +10215,7 @@        <key>Type</key>        <string>U32</string>        <key>Value</key> -      <integer>2</integer> +      <integer>0</integer>      </map>      <key>CallLogSortOrder</key>      <map> diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp index d28af3eff9..094d502078 100755 --- a/indra/newview/llagent.cpp +++ b/indra/newview/llagent.cpp @@ -1397,7 +1397,7 @@ void LLAgent::setDoNotDisturb(bool pIsDoNotDisturb)  	LLNotificationsUI::LLChannelManager::getInstance()->muteAllChannels(pIsDoNotDisturb);  	if (isDoNotDisturbSwitchedOff)  	{ -		LLDoNotDisturbNotificationStorage::getInstance()->loadNotifications(); +		LLDoNotDisturbNotificationStorage::getInstance()->updateNotifications();  	}  } diff --git a/indra/newview/llcommunicationchannel.cpp b/indra/newview/llcommunicationchannel.cpp index 4b0a70ffd8..0821510645 100644 --- a/indra/newview/llcommunicationchannel.cpp +++ b/indra/newview/llcommunicationchannel.cpp @@ -52,6 +52,11 @@ bool LLCommunicationChannel::filterByDoNotDisturbStatus(LLNotificationPtr)  	return !gAgent.isDoNotDisturb();  } +S32 LLCommunicationChannel::getHistorySize() const +{ +    return mHistory.size(); +} +  LLCommunicationChannel::history_list_t::const_iterator LLCommunicationChannel::beginHistory() const  {  	return mHistory.begin(); @@ -62,17 +67,46 @@ LLCommunicationChannel::history_list_t::const_iterator LLCommunicationChannel::e  	return mHistory.end();  } +LLCommunicationChannel::history_list_t::iterator LLCommunicationChannel::beginHistory() +{ +    return mHistory.begin(); +} + +LLCommunicationChannel::history_list_t::iterator LLCommunicationChannel::endHistory() +{ +    return mHistory.end(); +} +  void LLCommunicationChannel::clearHistory()  {  	mHistory.clear();  } +void LLCommunicationChannel::removeItemFromHistory(LLNotificationPtr p) +{ +    //Find the notification and removes it from mHistory +    for(history_list_t::iterator it = beginHistory(); it != endHistory(); ++it) +    { +        if(it->second == p) +        { +            mHistory.erase(it); +            break; +        } +    } +} + +void LLCommunicationChannel::onDelete(LLNotificationPtr p)  +{ +    removeItemFromHistory(p); +} +  void LLCommunicationChannel::onFilterFail(LLNotificationPtr pNotificationPtr)  {  	std::string notificationType = pNotificationPtr->getType();  	if ((notificationType == "groupnotify")  		|| (notificationType == "offer") -		|| (notificationType == "notifytoast")) +		|| (notificationType == "notifytoast") +        && !pNotificationPtr->isCancelled())  	{  		mHistory.insert(std::make_pair<LLDate, LLNotificationPtr>(pNotificationPtr->getDate(), pNotificationPtr));  	} diff --git a/indra/newview/llcommunicationchannel.h b/indra/newview/llcommunicationchannel.h index 0e15e1cd15..0d8f7f4387 100644 --- a/indra/newview/llcommunicationchannel.h +++ b/indra/newview/llcommunicationchannel.h @@ -44,12 +44,17 @@ public:  	static bool filterByDoNotDisturbStatus(LLNotificationPtr);  	typedef std::multimap<LLDate, LLNotificationPtr> history_list_t; +    S32 getHistorySize() const;	  	history_list_t::const_iterator beginHistory() const;  	history_list_t::const_iterator endHistory() const; -	 +    history_list_t::iterator beginHistory(); +    history_list_t::iterator endHistory();	 +  	void clearHistory(); +    void removeItemFromHistory(LLNotificationPtr p);  protected: +    virtual void onDelete(LLNotificationPtr p);  	virtual void onFilterFail(LLNotificationPtr pNotificationPtr);  private: diff --git a/indra/newview/lldonotdisturbnotificationstorage.cpp b/indra/newview/lldonotdisturbnotificationstorage.cpp index ac41a3804f..42b455c1ce 100644 --- a/indra/newview/lldonotdisturbnotificationstorage.cpp +++ b/indra/newview/lldonotdisturbnotificationstorage.cpp @@ -33,6 +33,7 @@  #include "lldir.h"  #include "llerror.h"  #include "llfasttimer_class.h" +#include "llfloaterreg.h"  #include "llnotifications.h"  #include "llnotificationhandler.h"  #include "llnotificationstorage.h" @@ -41,9 +42,34 @@  #include "llsingleton.h"  #include "lluuid.h" +static const F32 DND_TIMER = 3.0; + +LLDoNotDisturbNotificationStorageTimer::LLDoNotDisturbNotificationStorageTimer() : LLEventTimer(DND_TIMER) +{ +    mEventTimer.start(); +} + +LLDoNotDisturbNotificationStorageTimer::~LLDoNotDisturbNotificationStorageTimer() +{ +    mEventTimer.stop(); +} + +BOOL LLDoNotDisturbNotificationStorageTimer::tick() +{ +    LLDoNotDisturbNotificationStorage * doNotDisturbNotificationStorage =  LLDoNotDisturbNotificationStorage::getInstance(); + +    if(doNotDisturbNotificationStorage +        && doNotDisturbNotificationStorage->getDirty()) +    { +        doNotDisturbNotificationStorage->saveNotifications(); +    } +    return FALSE; +} +  LLDoNotDisturbNotificationStorage::LLDoNotDisturbNotificationStorage()  	: LLSingleton<LLDoNotDisturbNotificationStorage>()  	, LLNotificationStorage(gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, "dnd_notifications.xml")) +    , mDirty(false)  {  } @@ -56,6 +82,16 @@ void LLDoNotDisturbNotificationStorage::initialize()  	getCommunicationChannel()->connectFailedFilter(boost::bind(&LLDoNotDisturbNotificationStorage::onChannelChanged, this, _1));  } +bool LLDoNotDisturbNotificationStorage::getDirty() +{ +    return mDirty; +} + +void LLDoNotDisturbNotificationStorage::resetDirty() +{ +    mDirty = false; +} +  static LLFastTimer::DeclareTimer FTM_SAVE_DND_NOTIFICATIONS("Save DND Notifications");  void LLDoNotDisturbNotificationStorage::saveNotifications() @@ -82,6 +118,8 @@ void LLDoNotDisturbNotificationStorage::saveNotifications()  	}  	writeNotifications(output); + +    resetDirty();  }  static LLFastTimer::DeclareTimer FTM_LOAD_DND_NOTIFICATIONS("Load DND Notifications"); @@ -103,6 +141,7 @@ void LLDoNotDisturbNotificationStorage::loadNotifications()  	}  	LLNotifications& instance = LLNotifications::instance(); +    bool imToastExists = false;  	for (LLSD::array_const_iterator notification_it = data.beginArray();  		 notification_it != data.endArray(); @@ -110,17 +149,15 @@ void LLDoNotDisturbNotificationStorage::loadNotifications()  	{  		LLSD notification_params = *notification_it;          const LLUUID& notificationID = notification_params["id"]; +        std::string notificationName = notification_params["name"];          LLNotificationPtr notification = instance.find(notificationID); -		 -        //Notification already exists in notification pipeline (same instance of app running) -		if (notification) -		{ -            notification->setDND(true); -			instance.update(notification); -		} -        //Notification doesn't exist (different instance since restarted app while in DND mode) -		else -		{ + +        if(notificationName == "IMToast") +        { +            imToastExists = true; +        } + +        //New notification needs to be added              notification = (LLNotificationPtr) new LLNotification(notification_params.with("is_dnd", true));  			LLNotificationResponderInterface* responder = createResponder(notification_params["responder_sd"]["responder_type"], notification_params["responder_sd"]);  			if (responder == NULL) @@ -136,16 +173,58 @@ void LLDoNotDisturbNotificationStorage::loadNotifications()  			instance.add(notification);  		} -	} -	// Clear the communication channel history and rewrite the save file to empty it as well +    if(imToastExists) +    { +        LLFloaterReg::showInstance("im_container"); +    } + +    //writes out empty .xml file (since LLCommunicationChannel::mHistory is empty) +	saveNotifications(); +} + +void LLDoNotDisturbNotificationStorage::updateNotifications() +{ +  	LLNotificationChannelPtr channelPtr = getCommunicationChannel();  	LLCommunicationChannel *commChannel = dynamic_cast<LLCommunicationChannel*>(channelPtr.get());  	llassert(commChannel != NULL); + +    LLNotifications& instance = LLNotifications::instance(); +    bool imToastExists = false; +   +    for (LLCommunicationChannel::history_list_t::const_iterator it = commChannel->beginHistory(); +        it != commChannel->endHistory(); +        ++it) +    { +        LLNotificationPtr notification = it->second; +        std::string notificationName = notification->getName(); + +        if(notificationName == "IMToast") +        { +            imToastExists = true; +        } + +        //Notification already exists in notification pipeline (same instance of app running) +        if (notification) +        { +            notification->setDND(true); +            instance.update(notification); +        } +    } + +    if(imToastExists) +    {    +        LLFloaterReg::showInstance("im_container"); +    } + +    //When exit DND mode, write empty notifications file +    if(commChannel->getHistorySize()) +    {  	commChannel->clearHistory(); -	  	saveNotifications();  } +}  LLNotificationChannelPtr LLDoNotDisturbNotificationStorage::getCommunicationChannel() const  { @@ -154,12 +233,55 @@ LLNotificationChannelPtr LLDoNotDisturbNotificationStorage::getCommunicationChan  	return channelPtr;  } +void LLDoNotDisturbNotificationStorage::removeIMNotification(const LLUUID& session_id) +{ +    LLNotifications& instance = LLNotifications::instance(); +    LLNotificationChannelPtr channelPtr = getCommunicationChannel(); +    LLCommunicationChannel *commChannel = dynamic_cast<LLCommunicationChannel*>(channelPtr.get()); +    LLNotificationPtr notification; +    LLSD substitutions; +    LLUUID notificationSessionID; +    LLCommunicationChannel::history_list_t::iterator it; +    std::vector<LLCommunicationChannel::history_list_t::iterator> itemsToRemove; + +    //Find notification with the matching session id +    for (it = commChannel->beginHistory(); +        it != commChannel->endHistory();  +        ++it) +    { +        notification = it->second; +        substitutions = notification->getSubstitutions(); +        notificationSessionID = substitutions["SESSION_ID"].asUUID(); + +        if(session_id == notificationSessionID) +        { +            itemsToRemove.push_back(it); +        } +    } + +    +    //Remove the notifications +    if(itemsToRemove.size()) +    { +    while(itemsToRemove.size()) +    { +        it = itemsToRemove.back(); +        notification = it->second; +            commChannel->removeItemFromHistory(notification); +        instance.cancel(notification); +        itemsToRemove.pop_back(); +    } +        //Trigger saving of notifications to xml once all have been removed +        saveNotifications(); +    } +} +  bool LLDoNotDisturbNotificationStorage::onChannelChanged(const LLSD& pPayload)  {  	if (pPayload["sigtype"].asString() != "load")  	{ -		saveNotifications(); +        mDirty = true;  	}  	return false; diff --git a/indra/newview/lldonotdisturbnotificationstorage.h b/indra/newview/lldonotdisturbnotificationstorage.h index 60bcd89ec3..fd03b71357 100644 --- a/indra/newview/lldonotdisturbnotificationstorage.h +++ b/indra/newview/lldonotdisturbnotificationstorage.h @@ -28,12 +28,26 @@  #define LL_LLDONOTDISTURBNOTIFICATIONSTORAGE_H  #include "llerror.h" +#include "lleventtimer.h"  #include "llnotifications.h"  #include "llnotificationstorage.h"  #include "llsingleton.h"  class LLSD; +class LLDoNotDisturbNotificationStorageTimer : public LLEventTimer +{ +public: +    LLDoNotDisturbNotificationStorageTimer(); +    ~LLDoNotDisturbNotificationStorageTimer(); + +public: +    void startTimer(); +    void stopTimer(); +    bool isRunning(); +    BOOL tick(); +}; +  class LLDoNotDisturbNotificationStorage : public LLSingleton<LLDoNotDisturbNotificationStorage>, public LLNotificationStorage  {  	LOG_CLASS(LLDoNotDisturbNotificationStorage); @@ -42,13 +56,19 @@ public:  	~LLDoNotDisturbNotificationStorage();  	void initialize(); - +    bool getDirty(); +    void resetDirty();  	void saveNotifications();  	void loadNotifications(); +    void updateNotifications(); +    void removeIMNotification(const LLUUID& session_id);  protected:  private: +    bool mDirty; +    LLDoNotDisturbNotificationStorageTimer mTimer; +  	LLNotificationChannelPtr getCommunicationChannel() const;  	bool                     onChannelChanged(const LLSD& pPayload);  }; diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp index ac5ecc4b80..062a92b520 100644 --- a/indra/newview/llfloaterimcontainer.cpp +++ b/indra/newview/llfloaterimcontainer.cpp @@ -39,6 +39,7 @@  #include "llavatariconctrl.h"  #include "llavatarnamecache.h"  #include "llcallbacklist.h" +#include "lldonotdisturbnotificationstorage.h"  #include "llgroupactions.h"  #include "llgroupiconctrl.h"  #include "llflashtimer.h" @@ -1298,6 +1299,10 @@ BOOL LLFloaterIMContainer::selectConversationPair(const LLUUID& session_id, bool      	if (widget && widget->getParentFolder())      	{      		widget->getParentFolder()->setSelection(widget, FALSE, FALSE); +            if(gAgent.isDoNotDisturb()) +            { +                LLDoNotDisturbNotificationStorage::getInstance()->removeIMNotification(session_id); +            }      	}      } @@ -1319,6 +1324,11 @@ BOOL LLFloaterIMContainer::selectConversationPair(const LLUUID& session_id, bool  				// Switch to the conversation floater that is being selected  				selectFloater(session_floater);  			} + +            if(gAgent.isDoNotDisturb()) +            { +                LLDoNotDisturbNotificationStorage::getInstance()->removeIMNotification(session_id); +            }  		}  		// Set the focus on the selected floater diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index da811535e5..d0a8dfc0c8 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -128,18 +128,11 @@ void process_dnd_im(const LLSD& notification)              false,               false); //will need slight refactor to retrieve whether offline message or not (assume online for now)      } - -    // open conversation floater -	LLFloaterIMContainer* container_floater = -			LLFloaterReg::getTypedInstance<LLFloaterIMContainer>("im_container"); -	if (container_floater && !(container_floater->isFrontmost())) -	{ -		container_floater->openFloater(); -		container_floater->setFrontmost(TRUE); -	}  } + +  static void on_avatar_name_cache_toast(const LLUUID& agent_id,  									   const LLAvatarName& av_name,  									   LLSD msg) @@ -254,13 +247,22 @@ void on_new_message(const LLSD& msg)      {      	if (conversation_floater_not_focused)      	{ -            if(session_floater_not_focused) +            if(session_floater_not_focused && !gAgent.isDoNotDisturb())              {              	//User is not focused on conversation containing the message                  gToolBarView->flashCommand(LLCommandId("chat"), true);              }              im_box->flashConversationItemWidget(session_id, true); + +            //If a DND message, 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()) +            { +                LLAvatarNameCache::get(participant_id, boost::bind(&on_avatar_name_cache_toast, _1, _2, msg)); +            }          }      } @@ -272,9 +274,21 @@ void on_new_message(const LLSD& msg)              //Flash line item              im_box->flashConversationItemWidget(session_id, true); +            if(!gAgent.isDoNotDisturb()) +            {              //Surface conversations floater              LLFloaterReg::showInstance("im_container");          } + +            //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()) +            { +                LLAvatarNameCache::get(participant_id, boost::bind(&on_avatar_name_cache_toast, _1, _2, msg)); +    } +}      }  } @@ -2605,15 +2619,10 @@ void LLIMMgr::addMessage(  	// Open conversation floater if offline messages are present  	if (is_offline_msg)      { -		LLFloaterIMContainer* container_floater = -				LLFloaterReg::getTypedInstance<LLFloaterIMContainer>("im_container"); -		if (container_floater && !(container_floater->isFrontmost())) -		{ -			container_floater->openFloater(); -			container_floater->setFrontmost(TRUE); -		} +        LLFloaterReg::showInstance("im_container"); +	    LLFloaterReg::getTypedInstance<LLFloaterIMContainer>("im_container")-> +	    		flashConversationItemWidget(session_id, true);      } -  }  void LLIMMgr::addSystemMessage(const LLUUID& session_id, const std::string& message_name, const LLSD& args) diff --git a/indra/newview/llpanelblockedlist.cpp b/indra/newview/llpanelblockedlist.cpp index df1ccdd9fc..115114bb53 100644 --- a/indra/newview/llpanelblockedlist.cpp +++ b/indra/newview/llpanelblockedlist.cpp @@ -89,6 +89,9 @@ BOOL LLPanelBlockedList::postBuild()  	case E_SORT_BY_TYPE:  		mBlockedList->sortByType();  		break; +	default: +		llwarns << "Unrecognized sort order for blocked list" << llendl; +		break;  	}  	// Use the context menu of the Block list for the Block tab gear menu. diff --git a/indra/newview/lltoastnotifypanel.cpp b/indra/newview/lltoastnotifypanel.cpp index d494d12903..268b68b539 100644 --- a/indra/newview/lltoastnotifypanel.cpp +++ b/indra/newview/lltoastnotifypanel.cpp @@ -356,9 +356,8 @@ void LLToastNotifyPanel::init( LLRect rect, bool show_images )      if(rect != LLRect::null)      {          this->setShape(rect); -    }		  +    }      mInfoPanel = getChild<LLPanel>("info_panel"); -    mInfoPanel->setFollowsAll();      mControlPanel = getChild<LLPanel>("control_panel");      BUTTON_WIDTH = gSavedSettings.getS32("ToastButtonWidth"); @@ -453,10 +452,10 @@ void LLToastNotifyPanel::init( LLRect rect, bool show_images )              if(h_pad < 2*HPAD)              {                  /* -                * Probably it is a scriptdialog toast -                * for a scriptdialog toast h_pad can be < 2*HPAD if we have a lot of buttons. -                * In last case set default h_pad to avoid heaping of buttons  -                */ +                 * Probably it is a scriptdialog toast +                 * for a scriptdialog toast h_pad can be < 2*HPAD if we have a lot of buttons. +                 * In last case set default h_pad to avoid heaping of buttons  +                 */                  S32 button_per_row = button_panel_width / BUTTON_WIDTH;                  h_pad = (button_panel_width % BUTTON_WIDTH) / (button_per_row - 1);// -1  because we do not need space after last button in a row                     if(h_pad < 2*HPAD) // still not enough space between buttons ? @@ -491,10 +490,10 @@ void LLToastNotifyPanel::init( LLRect rect, bool show_images )              //mButtons.assign(buttons.begin(), buttons.end());          }      } +      // adjust panel's height to the text size +    mInfoPanel->setFollowsAll();      snapToMessageHeight(mTextBox, MAX_LENGTH); - -  } | 
