diff options
| author | Kent Quirk <q@lindenlab.com> | 2010-03-19 11:27:10 -0400 | 
|---|---|---|
| committer | Kent Quirk <q@lindenlab.com> | 2010-03-19 11:27:10 -0400 | 
| commit | 5e0be34c26f384a111063399b619c82b2a951dcd (patch) | |
| tree | 6b04bc67970f06c517436eea2b803406915bf8a7 | |
| parent | b84b0e71c12bb5ae7e9a6dafa1735a99f5975645 (diff) | |
| parent | d217adeede2d99ac6f48064388d91aa14ab9a4d2 (diff) | |
Merge
27 files changed, 634 insertions, 85 deletions
| diff --git a/indra/llmessage/llinstantmessage.cpp b/indra/llmessage/llinstantmessage.cpp index a9e1ee77ef..57e8a22546 100644 --- a/indra/llmessage/llinstantmessage.cpp +++ b/indra/llmessage/llinstantmessage.cpp @@ -61,6 +61,7 @@ const char EMPTY_BINARY_BUCKET[] = "";  const S32 EMPTY_BINARY_BUCKET_SIZE = 1;  const U32 NO_TIMESTAMP = 0;  const std::string SYSTEM_FROM("Second Life"); +const std::string INTERACTIVE_SYSTEM_FROM("F387446C-37C4-45f2-A438-D99CBDBB563B");  const S32 IM_TTL = 1; diff --git a/indra/llmessage/llinstantmessage.h b/indra/llmessage/llinstantmessage.h index 272e753f3c..f11b649f78 100644 --- a/indra/llmessage/llinstantmessage.h +++ b/indra/llmessage/llinstantmessage.h @@ -226,6 +226,7 @@ extern const S32 EMPTY_BINARY_BUCKET_SIZE;  extern const U32 NO_TIMESTAMP;  extern const std::string SYSTEM_FROM; +extern const std::string INTERACTIVE_SYSTEM_FROM;  // Number of retry attempts on sending the im.  extern const S32 IM_TTL; diff --git a/indra/llui/llnotifications.cpp b/indra/llui/llnotifications.cpp index 5816cef6af..56ec8c4262 100644 --- a/indra/llui/llnotifications.cpp +++ b/indra/llui/llnotifications.cpp @@ -402,7 +402,8 @@ LLNotification::LLNotification(const LLNotification::Params& p) :  	mRespondedTo(false),  	mPriority(p.priority),  	mCancelled(false), -	mIgnored(false) +	mIgnored(false), +	mResponderObj(NULL)  {  	if (p.functor.name.isChosen())  	{ @@ -416,6 +417,11 @@ LLNotification::LLNotification(const LLNotification::Params& p) :  		mTemporaryResponder = true;  	} +	if(p.responder.isProvided()) +	{ +		mResponderObj = p.responder; +	} +  	mId.generate();  	init(p.name, p.form_elements);  } @@ -425,7 +431,8 @@ LLNotification::LLNotification(const LLSD& sd) :  	mTemporaryResponder(false),  	mRespondedTo(false),  	mCancelled(false), -	mIgnored(false) +	mIgnored(false), +	mResponderObj(NULL)  {   	mId.generate();  	mSubstitutions = sd["substitutions"]; @@ -479,6 +486,7 @@ void LLNotification::updateFrom(LLNotificationPtr other)  	mForm = other->mForm;  	mResponseFunctorName = other->mResponseFunctorName;  	mRespondedTo = other->mRespondedTo; +	mResponse = other->mResponse;  	mTemporaryResponder = other->mTemporaryResponder;  	update(); @@ -556,14 +564,18 @@ std::string LLNotification::getSelectedOptionName(const LLSD& response)  void LLNotification::respond(const LLSD& response)  { +	// *TODO may remove mRespondedTo and use mResponce.isDefined() in isRespondedTo()  	mRespondedTo = true; +	mResponse = response;  	// look up the functor  	LLNotificationFunctorRegistry::ResponseFunctor functor =   		LLNotificationFunctorRegistry::instance().getFunctor(mResponseFunctorName);  	// and then call it  	functor(asLLSD(), response); -	if (mTemporaryResponder) +	bool is_resusable = getPayload()["reusable"].asBoolean(); + +	if (mTemporaryResponder && !is_resusable)  	{  		LLNotificationFunctorRegistry::instance().unregisterFunctor(mResponseFunctorName);  		mResponseFunctorName = ""; @@ -597,6 +609,16 @@ void LLNotification::setResponseFunctor(std::string const &responseFunctorName)  	mTemporaryResponder = false;  } +void LLNotification::setResponseFunctor(const LLNotificationFunctorRegistry::ResponseFunctor& cb) +{ +	if(mTemporaryResponder) +	{ +		LLNotificationFunctorRegistry::instance().unregisterFunctor(mResponseFunctorName); +	} + +	LLNotificationFunctorRegistry::instance().registerFunctor(mResponseFunctorName, cb); +} +  bool LLNotification::payloadContainsAll(const std::vector<std::string>& required_fields) const  {  	for(std::vector<std::string>::const_iterator required_fields_it = required_fields.begin();  @@ -856,7 +878,11 @@ bool LLNotificationChannelBase::updateItem(const LLSD& payload, LLNotificationPt  		if (wasFound)  		{  			abortProcessing = mChanged(payload); -			mItems.erase(pNotification); +			// do not delete the notification to make LLChatHistory::appendMessage add notification panel to IM window +			if( ! pNotification->getPayload()["reusable"].asBoolean() ) +			{ +				mItems.erase(pNotification); +			}  			onDelete(pNotification);  		}  	} diff --git a/indra/llui/llnotifications.h b/indra/llui/llnotifications.h index 8d993b71d7..a516a6723e 100644 --- a/indra/llui/llnotifications.h +++ b/indra/llui/llnotifications.h @@ -296,6 +296,7 @@ public:  		Optional<LLSD>							form_elements;  		Optional<LLDate>						time_stamp;  		Optional<LLNotificationContext*>		context; +		Optional<void*>							responder;  		struct Functor : public LLInitParam::Choice<Functor>  		{ @@ -317,6 +318,7 @@ public:  			form_elements("form_elements")  		{  			time_stamp = LLDate::now(); +			responder = NULL;  		}  		Params(const std::string& _name)  @@ -329,6 +331,7 @@ public:  			functor.name = _name;  			name = _name;  			time_stamp = LLDate::now(); +			responder = NULL;  		}  	}; @@ -341,9 +344,11 @@ private:  	LLDate mExpiresAt;  	bool mCancelled;  	bool mRespondedTo; 	// once the notification has been responded to, this becomes true +	LLSD mResponse;  	bool mIgnored;  	ENotificationPriority mPriority;  	LLNotificationFormPtr mForm; +	void* mResponderObj;  	// a reference to the template  	LLNotificationTemplatePtr mTemplatep; @@ -384,6 +389,8 @@ public:  	void setResponseFunctor(std::string const &responseFunctorName); +	void setResponseFunctor(const LLNotificationFunctorRegistry::ResponseFunctor& cb); +  	typedef enum e_response_template_type  	{  		WITHOUT_DEFAULT_BUTTON, @@ -423,6 +430,10 @@ public:  	void respond(const LLSD& sd); +	void* getResponder() { return mResponderObj; } + +	void setResponder(void* responder) { mResponderObj = responder; } +  	void setIgnored(bool ignore);  	bool isCancelled() const @@ -435,6 +446,8 @@ public:  		return mRespondedTo;  	} +	const LLSD& getResponse() { return mResponse; } +  	bool isIgnored() const  	{  		return mIgnored; diff --git a/indra/newview/llchathistory.cpp b/indra/newview/llchathistory.cpp index e1c96d4a16..ac60fe6ba6 100644 --- a/indra/newview/llchathistory.cpp +++ b/indra/newview/llchathistory.cpp @@ -447,6 +447,7 @@ LLChatHistory::LLChatHistory(const LLChatHistory::Params& p)  :	LLUICtrl(p),  	mMessageHeaderFilename(p.message_header),  	mMessageSeparatorFilename(p.message_separator), +	mMessagePlaintextSeparatorFilename(p.message_plaintext_separator),  	mLeftTextPad(p.left_text_pad),  	mRightTextPad(p.right_text_pad),  	mLeftWidgetPad(p.left_widget_pad), @@ -534,6 +535,12 @@ LLView* LLChatHistory::getSeparator()  	return separator;  } +LLView* LLChatHistory::getPlaintextSeparator() +{ +	LLPanel* separator = LLUICtrlFactory::getInstance()->createFromFile<LLPanel>(mMessagePlaintextSeparatorFilename, NULL, LLPanel::child_registry_t::instance()); +	return separator; +} +  LLView* LLChatHistory::getHeader(const LLChat& chat,const LLStyle::Params& style_params)  {  	LLChatHistoryHeader* header = LLChatHistoryHeader::createInstance(mMessageHeaderFilename); @@ -632,6 +639,15 @@ void LLChatHistory::appendMessage(const LLChat& chat, const LLSD &args, const LL  	if (use_plain_text_chat_history)  	{ +		// append plaintext separator +		LLView* separator = getPlaintextSeparator(); +		LLInlineViewSegment::Params p; +		p.force_newline = true; +		p.left_pad = mLeftWidgetPad; +		p.right_pad = mRightWidgetPad; +		p.view = separator; +		mEditor->appendWidget(p, "\n", false); +  		mEditor->appendText("[" + chat.mTimeStr + "] ", mEditor->getText().size() != 0, style_params);  		if (utf8str_trim(chat.mFromName).size() != 0) @@ -734,7 +750,7 @@ void LLChatHistory::appendMessage(const LLChat& chat, const LLSD &args, const LL  		LLNotificationPtr notification = LLNotificationsUtil::find(chat.mNotifId);  		if (notification != NULL)  		{ -			LLToastNotifyPanel* notify_box = new LLToastNotifyPanel( +			LLIMToastNotifyPanel* notify_box = new LLIMToastNotifyPanel(  					notification);  			//we can't set follows in xml since it broke toasts behavior  			notify_box->setFollowsLeft(); @@ -743,7 +759,9 @@ void LLChatHistory::appendMessage(const LLChat& chat, const LLSD &args, const LL  			ctrl_list_t ctrls = notify_box->getControlPanel()->getCtrlList();  			S32 offset = 0; -			for (ctrl_list_t::iterator it = ctrls.begin(); it != ctrls.end(); it++) +			// Children were added by addChild() which uses push_front to insert them into list, +			// so to get buttons in correct order reverse iterator is used (EXT-5906)  +			for (ctrl_list_t::reverse_iterator it = ctrls.rbegin(); it != ctrls.rend(); it++)  			{  				LLButton * button = dynamic_cast<LLButton*> (*it);  				if (button != NULL) diff --git a/indra/newview/llchathistory.h b/indra/newview/llchathistory.h index 950b32861b..dfe5ea98e6 100644 --- a/indra/newview/llchathistory.h +++ b/indra/newview/llchathistory.h @@ -47,6 +47,8 @@ class LLChatHistory : public LLUICtrl  			Optional<std::string>	message_header;  			//Message separator filename  			Optional<std::string>	message_separator; +			//Message plaintext  separator filename +			Optional<std::string>	message_plaintext_separator;  			//Text left padding from the scroll rect  			Optional<S32>			left_text_pad;  			//Text right padding from the scroll rect @@ -69,6 +71,7 @@ class LLChatHistory : public LLUICtrl  			Params()  			:	message_header("message_header"),  				message_separator("message_separator"), +				message_plaintext_separator("message_plaintext_separator"),  				left_text_pad("left_text_pad"),  				right_text_pad("right_text_pad"),  				left_widget_pad("left_widget_pad"), @@ -97,6 +100,11 @@ class LLChatHistory : public LLUICtrl  		 */  		LLView* getSeparator();  		/** +		 * Builds a message plaintext  separator. +		 * @return pointer to LLView separator object. +		 */ +		LLView* getPlaintextSeparator(); +		/**  		 * Builds a message header.  		 * @return pointer to LLView header object.  		 */ @@ -133,6 +141,7 @@ class LLChatHistory : public LLUICtrl  		std::string mMessageHeaderFilename;  		std::string mMessageSeparatorFilename; +		std::string mMessagePlaintextSeparatorFilename;  		S32 mLeftTextPad;  		S32 mRightTextPad; diff --git a/indra/newview/llimfloater.cpp b/indra/newview/llimfloater.cpp index 77eaebb0bc..f0e195c37a 100644 --- a/indra/newview/llimfloater.cpp +++ b/indra/newview/llimfloater.cpp @@ -454,7 +454,7 @@ void LLIMFloater::getAllowedRect(LLRect& rect)  void LLIMFloater::setDocked(bool docked, bool pop_on_undock)  {  	// update notification channel state -	LLNotificationsUI::LLScreenChannel* channel = dynamic_cast<LLNotificationsUI::LLScreenChannel*> +	LLNotificationsUI::LLScreenChannel* channel = static_cast<LLNotificationsUI::LLScreenChannel*>  		(LLNotificationsUI::LLChannelManager::getInstance()->  											findChannelByID(LLUUID(gSavedSettings.getString("NotificationChannelUUID")))); @@ -473,7 +473,7 @@ void LLIMFloater::setDocked(bool docked, bool pop_on_undock)  void LLIMFloater::setVisible(BOOL visible)  { -	LLNotificationsUI::LLScreenChannel* channel = dynamic_cast<LLNotificationsUI::LLScreenChannel*> +	LLNotificationsUI::LLScreenChannel* channel = static_cast<LLNotificationsUI::LLScreenChannel*>  		(LLNotificationsUI::LLChannelManager::getInstance()->  											findChannelByID(LLUUID(gSavedSettings.getString("NotificationChannelUUID"))));  	LLTransientDockableFloater::setVisible(visible); @@ -642,6 +642,24 @@ void LLIMFloater::updateMessages()  			if (msg.has("notification_id"))  			{  				chat.mNotifId = msg["notification_id"].asUUID(); +				// if notification exists - embed it +				if (LLNotificationsUtil::find(chat.mNotifId) != NULL) +				{ +					// remove embedded notification from channel +					LLNotificationsUI::LLScreenChannel* channel = static_cast<LLNotificationsUI::LLScreenChannel*> +							(LLNotificationsUI::LLChannelManager::getInstance()-> +																findChannelByID(LLUUID(gSavedSettings.getString("NotificationChannelUUID")))); +					if (getVisible()) +					{ +						// toast will be automatically closed since it is not storable toast +						channel->hideToast(chat.mNotifId); +					} +				} +				// if notification doesn't exist - try to use next message which should be log entry +				else +				{ +					continue; +				}  			}  			//process text message  			else @@ -651,6 +669,19 @@ void LLIMFloater::updateMessages()  			mChatHistory->appendMessage(chat, chat_args);  			mLastMessageIndex = msg["index"].asInteger(); + +			// if it is a notification - next message is a notification history log, so skip it +			if (chat.mNotifId.notNull() && LLNotificationsUtil::find(chat.mNotifId) != NULL) +			{ +				if (++iter == iter_end) +				{ +					break; +				} +				else +				{ +					mLastMessageIndex++; +				} +			}  		}  	}  } diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index b3f085ef6d..6ce06adc80 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -717,13 +717,22 @@ LLIMModel::LLIMSession* LLIMModel::addMessageSilently(const LLUUID& session_id,  		return NULL;  	} -	addToHistory(session_id, from, from_id, utf8_text); -	if (log2file) logToFile(session_id, from, from_id, utf8_text); +	// replace interactive system message marker with correct from string value +	std::string from_name = from; +	if (INTERACTIVE_SYSTEM_FROM == from) +	{ +		from_name = SYSTEM_FROM; +	} + +	addToHistory(session_id, from_name, from_id, utf8_text); +	if (log2file) logToFile(session_id, from_name, from_id, utf8_text);  	session->mNumUnread++;  	//update count of unread messages from real participant -	if (!(from_id.isNull() || from_id == gAgentID || SYSTEM_FROM == from)) +	if (!(from_id.isNull() || from_id == gAgentID || SYSTEM_FROM == from) +			// we should increment counter for interactive system messages() +			|| INTERACTIVE_SYSTEM_FROM == from)  	{  		++(session->mParticipantUnreadMessageCount);  	} diff --git a/indra/newview/llnotificationhandler.h b/indra/newview/llnotificationhandler.h index a163b6fd62..62daf5f105 100644 --- a/indra/newview/llnotificationhandler.h +++ b/indra/newview/llnotificationhandler.h @@ -298,6 +298,18 @@ public:  	static bool canSpawnSessionAndLogToIM(const LLNotificationPtr& notification);  	/** +	 * Checks if passed notification can create toast. +	 * +	 * It returns false only for inventory accepted/declined notifications if respective IM window is open (EXT-5909) +	 */ +	static bool canSpawnToast(const LLNotificationPtr& notification); + +	/** +	 * Determines whether IM floater is opened. +	 */ +	static bool isIMFloaterOpened(const LLNotificationPtr& notification); + +	/**  	 * Writes notification message to IM session.  	 */  	static void logToIM(const EInstantMessage& session_type, @@ -343,6 +355,16 @@ public:  	 * Adds notification panel to the IM floater.  	 */  	static void addNotifPanelToIM(const LLNotificationPtr& notification); + +	/** +	 * Updates messages of visible IM floater. +	 */ +	static void updateVisibleIMFLoaterMesages(const LLNotificationPtr& notification); + +	/** +	 * Decrements counter of IM messages. +	 */ +	static void decIMMesageCounter(const LLNotificationPtr& notification);  };  } diff --git a/indra/newview/llnotificationhandlerutil.cpp b/indra/newview/llnotificationhandlerutil.cpp index 88bb769109..5affd5c677 100644 --- a/indra/newview/llnotificationhandlerutil.cpp +++ b/indra/newview/llnotificationhandlerutil.cpp @@ -127,7 +127,9 @@ const static std::string GRANTED_MODIFY_RIGHTS("GrantedModifyRights"),  						FRIENDSHIP_DECLINED_BYME("FriendshipDeclinedByMe"),  						FRIEND_ONLINE("FriendOnline"), FRIEND_OFFLINE("FriendOffline"),  						SERVER_OBJECT_MESSAGE("ServerObjectMessage"), -						TELEPORT_OFFERED("TeleportOffered"); +						TELEPORT_OFFERED("TeleportOffered"), +						TELEPORT_OFFER_SENT("TeleportOfferSent"); +  // static  bool LLHandlerUtil::canLogToIM(const LLNotificationPtr& notification) @@ -137,11 +139,15 @@ bool LLHandlerUtil::canLogToIM(const LLNotificationPtr& notification)  			|| PAYMENT_RECIVED == notification->getName()  			|| OFFER_FRIENDSHIP == notification->getName()  			|| FRIENDSHIP_OFFERED == notification->getName() +			|| FRIENDSHIP_ACCEPTED == notification->getName()  			|| FRIENDSHIP_ACCEPTED_BYME == notification->getName()  			|| FRIENDSHIP_DECLINED_BYME == notification->getName()  			|| SERVER_OBJECT_MESSAGE == notification->getName()  			|| INVENTORY_ACCEPTED == notification->getName() -			|| INVENTORY_DECLINED == notification->getName(); +			|| INVENTORY_DECLINED == notification->getName() +			|| USER_GIVE_ITEM == notification->getName() +			|| TELEPORT_OFFERED == notification->getName() +			|| TELEPORT_OFFER_SENT == notification->getName();  }  // static @@ -158,20 +164,18 @@ bool LLHandlerUtil::canLogToNearbyChat(const LLNotificationPtr& notification)  bool LLHandlerUtil::canSpawnIMSession(const LLNotificationPtr& notification)  {  	return OFFER_FRIENDSHIP == notification->getName() -			|| FRIENDSHIP_ACCEPTED == notification->getName()  			|| USER_GIVE_ITEM == notification->getName() -			|| INVENTORY_ACCEPTED == notification->getName() -			|| INVENTORY_DECLINED == notification->getName(); +			|| TELEPORT_OFFERED == notification->getName();  }  // static  bool LLHandlerUtil::canAddNotifPanelToIM(const LLNotificationPtr& notification)  {  	return OFFER_FRIENDSHIP == notification->getName() -					|| USER_GIVE_ITEM == notification->getName(); +					|| USER_GIVE_ITEM == notification->getName() +					|| TELEPORT_OFFERED == notification->getName();  } -  // static  bool LLHandlerUtil::canSpawnSessionAndLogToIM(const LLNotificationPtr& notification)  { @@ -179,18 +183,57 @@ bool LLHandlerUtil::canSpawnSessionAndLogToIM(const LLNotificationPtr& notificat  }  // static +bool LLHandlerUtil::canSpawnToast(const LLNotificationPtr& notification) +{ +	bool cannot_spawn = isIMFloaterOpened(notification) && (INVENTORY_DECLINED == notification->getName() +			|| INVENTORY_ACCEPTED == notification->getName()); +	 +	return !cannot_spawn; +} + +// static +bool LLHandlerUtil::isIMFloaterOpened(const LLNotificationPtr& notification) +{ +	bool res = false; + +	LLUUID from_id = notification->getPayload()["from_id"]; +	LLUUID session_id = LLIMMgr::computeSessionID(IM_NOTHING_SPECIAL, +			from_id); + +	LLIMFloater* im_floater = LLFloaterReg::findTypedInstance<LLIMFloater>( +					"impanel", session_id); +	if (im_floater != NULL) +	{ +		res = im_floater->getVisible() == TRUE; +	} + +	return res; +} + +// static  void LLHandlerUtil::logToIM(const EInstantMessage& session_type,  		const std::string& session_name, const std::string& from_name,  		const std::string& message, const LLUUID& session_owner_id,  		const LLUUID& from_id)  { +	std::string from = from_name; +	if (from_name.empty()) +	{ +		from = SYSTEM_FROM; +	} +  	LLUUID session_id = LLIMMgr::computeSessionID(session_type,  			session_owner_id);  	LLIMModel::LLIMSession* session = LLIMModel::instance().findIMSession(  			session_id);  	if (session == NULL)  	{ -		LLIMModel::instance().logToFile(session_name, from_name, from_id, message); +		// replace interactive system message marker with correct from string value +		if (INTERACTIVE_SYSTEM_FROM == from_name) +		{ +			from = SYSTEM_FROM; +		} +		LLIMModel::instance().logToFile(session_name, from, from_id, message);  	}  	else  	{ @@ -201,8 +244,13 @@ void LLHandlerUtil::logToIM(const EInstantMessage& session_type,  		// set searched session as active to avoid IM toast popup  		LLIMModel::instance().setActiveSessionID(session_id); -		LLIMModel::instance().addMessage(session_id, from_name, from_id, +		S32 unread = session->mNumUnread; +		S32 participant_unread = session->mParticipantUnreadMessageCount; +		LLIMModel::instance().addMessageSilently(session_id, from, from_id,  				message); +		// we shouldn't increment counters when logging, so restore them +		session->mNumUnread = unread; +		session->mParticipantUnreadMessageCount = participant_unread;  		// restore active session id  		if (active_session_id.isNull()) @@ -250,13 +298,13 @@ void LLHandlerUtil::logToIMP2P(const LLNotificationPtr& notification, bool to_fi  		if(to_file_only)  		{ -			logToIM(IM_NOTHING_SPECIAL, session_name, name, notification->getMessage(), +			logToIM(IM_NOTHING_SPECIAL, session_name, "", notification->getMessage(),  					LLUUID(), LLUUID());  		}  		else  		{ -			logToIM(IM_NOTHING_SPECIAL, session_name, name, notification->getMessage(), -					from_id, from_id); +			logToIM(IM_NOTHING_SPECIAL, session_name, INTERACTIVE_SYSTEM_FROM, notification->getMessage(), +					from_id, LLUUID());  		}  	}  } @@ -324,7 +372,16 @@ std::string LLHandlerUtil::getSubstitutionName(const LLNotificationPtr& notifica  	if (res.empty())  	{  		LLUUID from_id = notification->getPayload()["FROM_ID"]; -		gCacheName->getFullName(from_id, res); + +		//*TODO all keys everywhere should be made of the same case, there is a mix of keys in lower and upper cases +		if (from_id.isNull())  +		{ +			from_id = notification->getPayload()["from_id"]; +		} +		if(!gCacheName->getFullName(from_id, res)) +		{ +			res = ""; +		}  	}  	return res;  } @@ -343,11 +400,54 @@ void LLHandlerUtil::addNotifPanelToIM(const LLNotificationPtr& notification)  	LLSD offer;  	offer["notification_id"] = notification->getID(); -	offer["from_id"] = notification->getPayload()["from_id"]; -	offer["from"] = name; -	offer["time"] = LLLogChat::timestamp(true); +	offer["from"] = SYSTEM_FROM; +	offer["time"] = LLLogChat::timestamp(false);  	offer["index"] = (LLSD::Integer)session->mMsgs.size();  	session->mMsgs.push_front(offer); -	LLIMFloater::show(session_id); + +	// update IM floater and counters +	LLSD arg; +	arg["session_id"] = session_id; +	arg["num_unread"] = ++(session->mNumUnread); +	arg["participant_unread"] = ++(session->mParticipantUnreadMessageCount); +	LLIMModel::getInstance()->mNewMsgSignal(arg); +} + +// static +void LLHandlerUtil::updateVisibleIMFLoaterMesages(const LLNotificationPtr& notification) +{ +	const std::string name = LLHandlerUtil::getSubstitutionName(notification); +	LLUUID from_id = notification->getPayload()["from_id"]; +	LLUUID session_id = spawnIMSession(name, from_id); + +	LLIMFloater* im_floater = LLIMFloater::findInstance(session_id); +	if (im_floater != NULL && im_floater->getVisible()) +	{ +		im_floater->updateMessages(); +	} +} + +// static +void LLHandlerUtil::decIMMesageCounter(const LLNotificationPtr& notification) +{ +	const std::string name = LLHandlerUtil::getSubstitutionName(notification); +	LLUUID from_id = notification->getPayload()["from_id"]; +	LLUUID session_id = LLIMMgr::computeSessionID(IM_NOTHING_SPECIAL, from_id); + +	LLIMModel::LLIMSession * session = LLIMModel::getInstance()->findIMSession( +			session_id); + +	if (session == NULL) +	{ +		return; +	} + +	LLSD arg; +	arg["session_id"] = session_id; +	session->mNumUnread--; +	arg["num_unread"] = session->mNumUnread; +	session->mParticipantUnreadMessageCount--; +	arg["participant_unread"] = session->mParticipantUnreadMessageCount; +	LLIMModel::getInstance()->mNewMsgSignal(arg);  } diff --git a/indra/newview/llnotificationofferhandler.cpp b/indra/newview/llnotificationofferhandler.cpp index 8ebd5de258..0a42d8adbe 100644 --- a/indra/newview/llnotificationofferhandler.cpp +++ b/indra/newview/llnotificationofferhandler.cpp @@ -113,35 +113,58 @@ bool LLOfferHandler::processNotification(const LLSD& notify)  				session_id = LLHandlerUtil::spawnIMSession(name, from_id);  			} -			if (LLHandlerUtil::canAddNotifPanelToIM(notification)) +			bool show_toast = true; +			bool add_notid_to_im = LLHandlerUtil::canAddNotifPanelToIM(notification); +			if (add_notid_to_im)  			{  				LLHandlerUtil::addNotifPanelToIM(notification); -				LLHandlerUtil::logToIMP2P(notification, true); +				if (LLHandlerUtil::isIMFloaterOpened(notification)) +				{ +					show_toast = false; +				}  			} -			else if (notification->getPayload().has("SUPPRESS_TOAST") + +			if (notification->getPayload().has("SUPPRESS_TOAST")  						&& notification->getPayload()["SUPPRESS_TOAST"])  			{ -				LLHandlerUtil::logToIMP2P(notification);  				LLNotificationsUtil::cancel(notification);  			} -			else +			else if(show_toast)  			{  				LLToastNotifyPanel* notify_box = new LLToastNotifyPanel(notification); - +				// don't close notification on panel destroy since it will be used by IM floater +				notify_box->setCloseNotificationOnDestroy(!add_notid_to_im);  				LLToast::Params p;  				p.notif_id = notification->getID();  				p.notification = notification;  				p.panel = notify_box;  				p.on_delete_toast = boost::bind(&LLOfferHandler::onDeleteToast, this, _1); +				// we not save offer notifications to the syswell floater that should be added to the IM floater +				p.can_be_stored = !add_notid_to_im;  				LLScreenChannel* channel = dynamic_cast<LLScreenChannel*>(mChannel);  				if(channel)  					channel->addToast(p); -				LLHandlerUtil::logToIMP2P(notification); +				// if we not add notification to IM - add it to notification well +				if (!add_notid_to_im) +				{ +					// send a signal to the counter manager +					mNewNotificationSignal(); +				} +			} -				// send a signal to the counter manager -				mNewNotificationSignal(); +			if (LLHandlerUtil::canLogToIM(notification)) +			{ +				// log only to file if notif panel can be embedded to IM and IM is opened +				if (add_notid_to_im && LLHandlerUtil::isIMFloaterOpened(notification)) +				{ +					LLHandlerUtil::logToIMP2P(notification, true); +				} +				else +				{ +					LLHandlerUtil::logToIMP2P(notification); +				}  			}  		}  	} @@ -155,6 +178,11 @@ bool LLOfferHandler::processNotification(const LLSD& notify)  		}  		else  		{ +			if (LLHandlerUtil::canAddNotifPanelToIM(notification) +					&& !LLHandlerUtil::isIMFloaterOpened(notification)) +			{ +				LLHandlerUtil::decIMMesageCounter(notification); +			}  			mChannel->killToastByNotificationID(notification->getID());  		}  	} @@ -166,8 +194,11 @@ bool LLOfferHandler::processNotification(const LLSD& notify)  void LLOfferHandler::onDeleteToast(LLToast* toast)  { -	// send a signal to the counter manager -	mDelNotificationSignal(); +	if (!LLHandlerUtil::canAddNotifPanelToIM(toast->getNotification())) +	{ +		// send a signal to the counter manager +		mDelNotificationSignal(); +	}  	// send a signal to a listener to let him perform some action  	// in this case listener is a SysWellWindow and it will remove a corresponding item from its list @@ -181,7 +212,9 @@ void LLOfferHandler::onRejectToast(LLUUID& id)  	if (notification  			&& LLNotificationManager::getInstance()->getHandlerForNotification( -					notification->getType()) == this) +					notification->getType()) == this +					// don't delete notification since it may be used by IM floater +					&& !LLHandlerUtil::canAddNotifPanelToIM(notification))  	{  		LLNotifications::instance().cancel(notification);  	} diff --git a/indra/newview/llnotificationtiphandler.cpp b/indra/newview/llnotificationtiphandler.cpp index 4e2c5085ed..1f1afe293a 100644 --- a/indra/newview/llnotificationtiphandler.cpp +++ b/indra/newview/llnotificationtiphandler.cpp @@ -150,6 +150,12 @@ bool LLTipHandler::processNotification(const LLSD& notify)  			LLHandlerUtil::spawnIMSession(name, from_id);  		} +		// don't spawn toast for inventory accepted/declined offers if respective IM window is open (EXT-5909) +		if (!LLHandlerUtil::canSpawnToast(notification)) +		{ +			return true; +		} +  		LLToastPanel* notify_box = NULL;  		if("FriendOffline" == notification->getName() || "FriendOnline" == notification->getName())  		{ diff --git a/indra/newview/llpanelavatar.cpp b/indra/newview/llpanelavatar.cpp index 57b478ffef..a0ba2f739b 100644 --- a/indra/newview/llpanelavatar.cpp +++ b/indra/newview/llpanelavatar.cpp @@ -495,6 +495,7 @@ BOOL LLPanelAvatarProfile::postBuild()  			&LLPanelAvatarProfile::onMapButtonClick, this)), NULL);  	LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar; +	registrar.add("Profile.ShowOnMap",  boost::bind(&LLPanelAvatarProfile::onMapButtonClick, this));  	registrar.add("Profile.Pay",  boost::bind(&LLPanelAvatarProfile::pay, this));  	registrar.add("Profile.Share", boost::bind(&LLPanelAvatarProfile::share, this));  	registrar.add("Profile.BlockUnblock", boost::bind(&LLPanelAvatarProfile::toggleBlock, this)); @@ -504,6 +505,7 @@ BOOL LLPanelAvatarProfile::postBuild()  	registrar.add("Profile.CSR", boost::bind(&LLPanelAvatarProfile::csr, this));  	LLUICtrl::EnableCallbackRegistry::ScopedRegistrar enable; +	enable.add("Profile.EnableShowOnMap", boost::bind(&LLPanelAvatarProfile::enableShowOnMap, this));  	enable.add("Profile.EnableGod", boost::bind(&enable_god));  	enable.add("Profile.EnableBlock", boost::bind(&LLPanelAvatarProfile::enableBlock, this));  	enable.add("Profile.EnableUnblock", boost::bind(&LLPanelAvatarProfile::enableUnblock, this)); @@ -698,6 +700,15 @@ void LLPanelAvatarProfile::toggleBlock()  	LLAvatarActions::toggleBlock(getAvatarId());  } +bool LLPanelAvatarProfile::enableShowOnMap() +{ +	bool is_buddy_online = LLAvatarTracker::instance().isBuddyOnline(getAvatarId()); + +	bool enable_map_btn = (is_buddy_online && is_agent_mappable(getAvatarId())) +		|| gAgent.isGodlike(); +	return enable_map_btn; +} +  bool LLPanelAvatarProfile::enableBlock()  {  	return LLAvatarActions::canBlock(getAvatarId()) && !LLAvatarActions::isBlocked(getAvatarId()); diff --git a/indra/newview/llpanelavatar.h b/indra/newview/llpanelavatar.h index 2bd23b6e9c..bb8df2ff9c 100644 --- a/indra/newview/llpanelavatar.h +++ b/indra/newview/llpanelavatar.h @@ -202,6 +202,7 @@ protected:  	void unfreeze();  	void csr(); +	bool enableShowOnMap();  	bool enableBlock();  	bool enableUnblock();  	bool enableGod(); diff --git a/indra/newview/llscreenchannel.cpp b/indra/newview/llscreenchannel.cpp index a4426b370e..dffb5e5e12 100644 --- a/indra/newview/llscreenchannel.cpp +++ b/indra/newview/llscreenchannel.cpp @@ -710,9 +710,7 @@ void LLScreenChannel::hideToast(const LLUUID& notification_id)  	if(mToastList.end() != it)  	{  		ToastElem te = *it; -		te.toast->setVisible(FALSE); -		te.toast->stopTimer(); -		mToastList.erase(it); +		te.toast->hide();  	}  } diff --git a/indra/newview/lltoastnotifypanel.cpp b/indra/newview/lltoastnotifypanel.cpp index e6d13a7613..d7a3bc1462 100644 --- a/indra/newview/lltoastnotifypanel.cpp +++ b/indra/newview/lltoastnotifypanel.cpp @@ -44,6 +44,7 @@  #include "llrect.h"  #include "lltrans.h"  #include "llnotificationsutil.h" +#include "llviewermessage.h"  const S32 BOTTOM_PAD = VPAD * 3;  const S32 IGNORE_BTN_TOP_DELTA = 3*VPAD;//additional ignore_btn padding @@ -53,6 +54,8 @@ S32 BUTTON_WIDTH = 90;  const LLFontGL* LLToastNotifyPanel::sFont = NULL;  const LLFontGL* LLToastNotifyPanel::sFontSmall = NULL; +LLToastNotifyPanel::button_click_signal_t LLToastNotifyPanel::sButtonClickSignal; +  LLToastNotifyPanel::LLToastNotifyPanel(LLNotificationPtr& notification, const LLRect& rect) :   LLToastPanel(notification),  mTextBox(NULL), @@ -60,7 +63,8 @@ mInfoPanel(NULL),  mControlPanel(NULL),  mNumOptions(0),  mNumButtons(0), -mAddedDefaultBtn(false) +mAddedDefaultBtn(false), +mCloseNotificationOnDestroy(true)  {  	LLUICtrlFactory::getInstance()->buildPanel(this, "panel_notification.xml");  	if(rect != LLRect::null) @@ -193,11 +197,25 @@ mAddedDefaultBtn(false)  			// we need to keep min width and max height to make visible all buttons, because width of the toast can not be changed  			adjustPanelForScriptNotice(button_panel_width, button_panel_height);  			updateButtonsLayout(buttons, h_pad); +			// save buttons for later use in disableButtons() +			mButtons.assign(buttons.begin(), buttons.end());  		}  	}  	// adjust panel's height to the text size  	mInfoPanel->setFollowsAll();  	snapToMessageHeight(mTextBox, MAX_LENGTH); + +	if(notification->getPayload()["reusable"].asBoolean()) +	{ +		mButtonClickConnection = sButtonClickSignal.connect( +			boost::bind(&LLToastNotifyPanel::onToastPanelButtonClicked, this, _1, _2)); + +		if(notification->isRespondedTo()) +		{ +			// User selected an option in toast, now disable required buttons in IM window +			disableRespondedOptions(notification); +		} +	}  }  void LLToastNotifyPanel::addDefaultButton()  { @@ -265,8 +283,10 @@ LLButton* LLToastNotifyPanel::createButton(const LLSD& form_element, BOOL is_opt  LLToastNotifyPanel::~LLToastNotifyPanel()   { +	mButtonClickConnection.disconnect(); +  	std::for_each(mBtnCallbackData.begin(), mBtnCallbackData.end(), DeletePointer()); -	if (LLNotificationsUtil::find(mNotification->getID()) != NULL) +	if (mCloseNotificationOnDestroy && LLNotificationsUtil::find(mNotification->getID()) != NULL)  	{  		LLNotifications::getInstance()->cancel(mNotification);  	} @@ -342,6 +362,104 @@ void LLToastNotifyPanel::adjustPanelForTipNotice()  	}  } +typedef std::set<std::string> button_name_set_t; +typedef std::map<std::string, button_name_set_t> disable_button_map_t; + +disable_button_map_t initUserGiveItemDisableButtonMap() +{ +	// see EXT-5905 for disable rules + +	disable_button_map_t disable_map; +	button_name_set_t buttons; + +	buttons.insert("Show"); +	disable_map.insert(std::make_pair("Show", buttons)); + +	buttons.insert("Discard"); +	disable_map.insert(std::make_pair("Discard", buttons)); + +	buttons.insert("Mute"); +	disable_map.insert(std::make_pair("Mute", buttons)); + +	return disable_map; +} + +disable_button_map_t initTeleportOfferedDisableButtonMap() +{ +	disable_button_map_t disable_map; +	button_name_set_t buttons; + +	buttons.insert("Teleport"); +	buttons.insert("Cancel"); + +	disable_map.insert(std::make_pair("Teleport", buttons)); +	disable_map.insert(std::make_pair("Cancel", buttons)); + +	return disable_map; +} + +disable_button_map_t initFriendshipOfferedDisableButtonMap() +{ +	disable_button_map_t disable_map; +	button_name_set_t buttons; + +	buttons.insert("Accept"); +	buttons.insert("Decline"); + +	disable_map.insert(std::make_pair("Accept", buttons)); +	disable_map.insert(std::make_pair("Decline", buttons)); + +	return disable_map; +} + +button_name_set_t getButtonDisableList(const std::string& notification_name, const std::string& button_name) +{ +	static disable_button_map_t user_give_item_disable_map = initUserGiveItemDisableButtonMap(); +	static disable_button_map_t teleport_offered_disable_map = initTeleportOfferedDisableButtonMap(); +	static disable_button_map_t friendship_offered_disable_map = initFriendshipOfferedDisableButtonMap(); + +	disable_button_map_t::const_iterator it; +	disable_button_map_t::const_iterator it_end; +	disable_button_map_t search_map; + +	if("UserGiveItem" == notification_name) +	{ +		search_map = user_give_item_disable_map; +	} +	else if("TeleportOffered" == notification_name) +	{ +		search_map = teleport_offered_disable_map; +	} +	else if("OfferFriendship" == notification_name) +	{ +		search_map = friendship_offered_disable_map; +	} + +	it = search_map.find(button_name); +	it_end = search_map.end(); + +	if(it_end != it) +	{ +		return it->second; +	} +	return button_name_set_t(); +} + +void LLToastNotifyPanel::disableButtons(const std::string& notification_name, const std::string& selected_button) +{ +	button_name_set_t buttons = getButtonDisableList(notification_name, selected_button); + +	std::vector<index_button_pair_t>::const_iterator it = mButtons.begin(); +	for ( ; it != mButtons.end(); it++) +	{ +		LLButton* btn = it->second; +		if(buttons.find(btn->getName()) != buttons.end()) +		{ +			btn->setEnabled(FALSE); +		} +	} +} +  // static  void LLToastNotifyPanel::onClickButton(void* data)  { @@ -354,8 +472,81 @@ void LLToastNotifyPanel::onClickButton(void* data)  	{  		response[button_name] = true;  	} +	 +	bool is_reusable = self->mNotification->getPayload()["reusable"].asBoolean(); +	// When we call respond(), LLOfferInfo will delete itself in inventory_offer_callback(),  +	// lets copy it while it's still valid. +	LLOfferInfo* old_info = static_cast<LLOfferInfo*>(self->mNotification->getResponder()); +	LLOfferInfo* new_info = NULL; +	if(is_reusable && old_info) +	{ +		new_info = new LLOfferInfo(*old_info); +		self->mNotification->setResponder(new_info); +	} +  	self->mNotification->respond(response); -	// disable all buttons -	self->mControlPanel->setEnabled(FALSE); +	if(is_reusable) +	{ +		sButtonClickSignal(self->mNotification->getID(), button_name); + +		if(new_info) +		{ +			self->mNotification->setResponseFunctor( +				boost::bind(&LLOfferInfo::inventory_offer_callback, new_info, _1, _2)); +		} +	} +	else +	{ +		// disable all buttons +		self->mControlPanel->setEnabled(FALSE); +	}  } + +void LLToastNotifyPanel::onToastPanelButtonClicked(const LLUUID& notification_id, const std::string btn_name) +{ +	if(mNotification->getID() == notification_id) +	{ +		disableButtons(mNotification->getName(), btn_name); +	} +} + +void LLToastNotifyPanel::disableRespondedOptions(LLNotificationPtr& notification) +{ +	LLSD response = notification->getResponse(); +	for (LLSD::map_const_iterator response_it = response.beginMap();  +		response_it != response.endMap(); ++response_it) +	{ +		if (response_it->second.isBoolean() && response_it->second.asBoolean()) +		{ +			// that after multiple responses there can be many pressed buttons +			// need to process them all +			disableButtons(notification->getName(), response_it->first); +		} +	} +} + + +////////////////////////////////////////////////////////////////////////// + +LLIMToastNotifyPanel::LLIMToastNotifyPanel(LLNotificationPtr& pNotification, const LLRect& rect /* = LLRect::null */) + : LLToastNotifyPanel(pNotification, rect) +{ +	mTextBox->setFollowsAll(); +} + +void LLIMToastNotifyPanel::reshape(S32 width, S32 height, BOOL called_from_parent /* = TRUE */) +{ +	S32 text_height = mTextBox->getTextBoundingRect().getHeight(); +	S32 widget_height = mTextBox->getRect().getHeight(); +	S32 delta = text_height - widget_height; +	LLRect rc = getRect(); + +	rc.setLeftTopAndSize(rc.mLeft, rc.mTop, width, height + delta); +	height = rc.getHeight(); +	width = rc.getWidth(); + +	LLToastPanel::reshape(width, height, called_from_parent); +} + +// EOF diff --git a/indra/newview/lltoastnotifypanel.h b/indra/newview/lltoastnotifypanel.h index 152975e7de..a8d2d03236 100644 --- a/indra/newview/lltoastnotifypanel.h +++ b/indra/newview/lltoastnotifypanel.h @@ -65,6 +65,7 @@ public:  	virtual ~LLToastNotifyPanel();  	LLPanel * getControlPanel() { return mControlPanel; } +	void setCloseNotificationOnDestroy(bool close) { mCloseNotificationOnDestroy = close; }  protected:  	LLButton* createButton(const LLSD& form_element, BOOL is_option); @@ -76,7 +77,7 @@ protected:  	};  	std::vector<InstanceAndS32*> mBtnCallbackData; -private: +	bool mCloseNotificationOnDestroy;  	typedef std::pair<int,LLButton*> index_button_pair_t;   	void adjustPanelForScriptNotice(S32 max_width, S32 max_height); @@ -90,6 +91,13 @@ private:  	 */  	void updateButtonsLayout(const std::vector<index_button_pair_t>& buttons, S32 h_pad); +	/** +	 * Disable specific button(s) based on notification name and clicked button +	 */ +	void disableButtons(const std::string& notification_name, const std::string& selected_button); + +	std::vector<index_button_pair_t> mButtons; +  	// panel elements  	LLTextBase*		mTextBox;  	LLPanel*		mInfoPanel;		// a panel, that contains an information @@ -98,6 +106,21 @@ private:  	// internal handler for button being clicked  	static void onClickButton(void* data); +	typedef boost::signals2::signal <void (const LLUUID& notification_id, const std::string btn_name)> +		button_click_signal_t; +	static button_click_signal_t sButtonClickSignal; +	boost::signals2::connection mButtonClickConnection; + +	/** +	 * handle sButtonClickSignal (to disable buttons) across all panels with given notification_id +	 */ +	void onToastPanelButtonClicked(const LLUUID& notification_id, const std::string btn_name); + +	/** +	 * Process response data. Will disable selected options +	 */ +	void disableRespondedOptions(LLNotificationPtr& notification); +  	bool mIsTip;  	bool mAddedDefaultBtn;  	bool mIsScriptDialog; @@ -111,4 +134,13 @@ private:  	static const LLFontGL* sFontSmall;  }; +class LLIMToastNotifyPanel : public LLToastNotifyPanel +{ +public: + +	LLIMToastNotifyPanel(LLNotificationPtr& pNotification, const LLRect& rect = LLRect::null); + +	/*virtual*/ void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE); +}; +  #endif /* LLTOASTNOTIFYPANEL_H_ */ diff --git a/indra/newview/lltooldraganddrop.cpp b/indra/newview/lltooldraganddrop.cpp index 125c62474e..47e60a966e 100644 --- a/indra/newview/lltooldraganddrop.cpp +++ b/indra/newview/lltooldraganddrop.cpp @@ -1503,15 +1503,38 @@ void LLToolDragAndDrop::commitGiveInventoryItem(const LLUUID& to_agent,  	LLMuteList::getInstance()->autoRemove(to_agent, LLMuteList::AR_INVENTORY); +	logInventoryOffer(to_agent, im_session_id);	 + +	// add buddy to recent people list +	LLRecentPeople::instance().add(to_agent); +} + +//static +void LLToolDragAndDrop::logInventoryOffer(const LLUUID& to_agent, const LLUUID &im_session_id) +{ +	// compute id of possible IM session with agent that has "to_agent" id +	LLUUID session_id = LLIMMgr::computeSessionID(IM_NOTHING_SPECIAL, to_agent);  	// If this item was given by drag-and-drop into an IM panel, log this action in the IM panel chat. -	if (im_session_id != LLUUID::null) +	if (im_session_id.notNull())  	{  		LLSD args;  		gIMMgr->addSystemMessage(im_session_id, "inventory_item_offered", args);  	} - -	// add buddy to recent people list -	LLRecentPeople::instance().add(to_agent); +	// If this item was given by drag-and-drop on avatar while IM panel was open, log this action in the IM panel chat. +	else if (LLIMModel::getInstance()->findIMSession(session_id)) +	{ +		LLSD args; +		gIMMgr->addSystemMessage(session_id, "inventory_item_offered", args); +	} +	// If this item was given by drag-and-drop on avatar while IM panel wasn't open, log this action to IM history. +	else +	{ +		std::string full_name; +		if (gCacheName->getFullName(to_agent, full_name)) +		{ +			LLIMModel::instance().logToFile(full_name, LLTrans::getString("SECOND_LIFE"), im_session_id, LLTrans::getString("inventory_item_offered-im")); +		} +	}  }  void LLToolDragAndDrop::giveInventoryCategory(const LLUUID& to_agent, @@ -1723,12 +1746,7 @@ void LLToolDragAndDrop::commitGiveInventoryCategory(const LLUUID& to_agent,  		LLMuteList::getInstance()->autoRemove(to_agent, LLMuteList::AR_INVENTORY); -		// If this item was given by drag-and-drop into an IM panel, log this action in the IM panel chat. -		if (im_session_id != LLUUID::null) -		{ -			LLSD args; -			gIMMgr->addSystemMessage(im_session_id, "inventory_item_offered", args); -		} +		logInventoryOffer(to_agent, im_session_id);  	}  } diff --git a/indra/newview/lltooldraganddrop.h b/indra/newview/lltooldraganddrop.h index 79b2bc32a3..0da13dac8b 100644 --- a/indra/newview/lltooldraganddrop.h +++ b/indra/newview/lltooldraganddrop.h @@ -227,6 +227,10 @@ protected:  											LLInventoryCategory* cat,  											const LLUUID &im_session_id = LLUUID::null); +	// log "Inventory item offered" to IM +	static void logInventoryOffer(const LLUUID& to_agent,  +									const LLUUID &im_session_id = LLUUID::null); +  public:  	// helper functions  	static BOOL isInventoryDropAcceptable(LLViewerObject* obj, LLInventoryItem* item) { return (ACCEPT_YES_COPY_SINGLE <= willObjectAcceptInventory(obj, item)); } diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index 32edbec822..7ecff4c2d8 100644 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -1084,6 +1084,21 @@ LLOfferInfo::LLOfferInfo(const LLSD& sd)  	mHost = LLHost(sd["sender"].asString());  } +LLOfferInfo::LLOfferInfo(const LLOfferInfo& info) +{ +	mIM = info.mIM; +	mFromID = info.mFromID; +	mFromGroup = info.mFromGroup; +	mFromObject = info.mFromObject; +	mTransactionID = info.mTransactionID; +	mFolderID = info.mFolderID; +	mObjectID = info.mObjectID; +	mType = info.mType; +	mFromName = info.mFromName; +	mDesc = info.mDesc; +	mHost = info.mHost; +} +  LLSD LLOfferInfo::asLLSD()  {  	LLSD sd; @@ -1575,7 +1590,12 @@ void inventory_offer_handler(LLOfferInfo* info)  	}  	else // Agent -> Agent Inventory Offer  	{ +		payload["reusable"] = true; +		p.responder = info;  		// Note: sets inventory_offer_callback as the callback +		// *TODO fix memory leak +		// inventory_offer_callback() is not invoked if user received notification and  +		// closes viewer(without responding the notification)  		p.substitutions(args).payload(payload).functor.function(boost::bind(&LLOfferInfo::inventory_offer_callback, info, _1, _2));  		p.name = "UserGiveItem"; @@ -2303,6 +2323,7 @@ void process_improved_im(LLMessageSystem *msg, void **user_data)  				payload["from_id"] = from_id;  				payload["lure_id"] = session_id;  				payload["godlike"] = FALSE; +				payload["reusable"] = true;  				LLNotificationsUtil::add("TeleportOffered", args, payload);  			}  		} @@ -2371,6 +2392,7 @@ void process_improved_im(LLMessageSystem *msg, void **user_data)  				}  				else  				{ +					payload["reusable"] = true;  					args["[MESSAGE]"] = message;  				        LLNotificationsUtil::add("OfferFriendship", args, payload);  				} @@ -4513,7 +4535,7 @@ void process_money_balance_reply( LLMessageSystem* msg, void** )  				// Each set of parenthesis will later be used to find arguments of message we generate  				// in the end of this if- (.*) gives us name of money receiver, (\\d+)-amount of money we pay  				// and ([^$]*)- reason of payment -				boost::regex expr("You paid (.*)L\\$(\\d+)\\s?([^$]*)."); +				boost::regex expr("You paid (?:.{0}|(.*) )L\\$(\\d+)\\s?([^$]*)\\.");  				boost::match_results <std::string::const_iterator> matches;  				if(boost::regex_match(desc, matches, expr))  				{ @@ -5545,6 +5567,8 @@ bool handle_lure_callback(const LLSD& notification, const LLSD& response)  				args["TO_NAME"] = target_name;  				LLSD payload; +				 +				//*TODO please rewrite all keys to the same case, lower or upper  				payload["from_id"] = target_id;  				payload["SESSION_NAME"] = target_name;  				payload["SUPPRESS_TOAST"] = true; diff --git a/indra/newview/llviewermessage.h b/indra/newview/llviewermessage.h index 7dd629dcfd..88f9697037 100644 --- a/indra/newview/llviewermessage.h +++ b/indra/newview/llviewermessage.h @@ -215,6 +215,8 @@ struct LLOfferInfo  		mIM(IM_NOTHING_SPECIAL), mType(LLAssetType::AT_NONE) {};  	LLOfferInfo(const LLSD& sd); +	LLOfferInfo(const LLOfferInfo& info); +  	void forceResponse(InventoryOfferResponse response);  	EInstantMessage mIM; diff --git a/indra/newview/skins/default/xui/de/panel_bottomtray.xml b/indra/newview/skins/default/xui/de/panel_bottomtray.xml index d3f89b0ad3..d52b8dcf4d 100644 --- a/indra/newview/skins/default/xui/de/panel_bottomtray.xml +++ b/indra/newview/skins/default/xui/de/panel_bottomtray.xml @@ -9,7 +9,7 @@  	<layout_stack name="toolbar_stack">  		<layout_panel name="speak_panel">  			<talk_button name="talk"> -				<speak_button label="Sprechen" label_selected="Sprechen" name="speak_btn"/> +				<speak_button label="Sprechen" label_selected="Sprechen" name="speak_btn" halign="right" />  			</talk_button>  		</layout_panel>  		<layout_panel name="gesture_panel"> diff --git a/indra/newview/skins/default/xui/en/menu_profile_overflow.xml b/indra/newview/skins/default/xui/en/menu_profile_overflow.xml index 5162a4902f..b0b7b554b0 100644 --- a/indra/newview/skins/default/xui/en/menu_profile_overflow.xml +++ b/indra/newview/skins/default/xui/en/menu_profile_overflow.xml @@ -6,6 +6,15 @@   name="profile_overflow_menu"   width="120">      <menu_item_call +     label="Map" +     layout="topleft" +     name="show_on_map"> +        <menu_item_call.on_click +         function="Profile.ShowOnMap" /> +        <menu_item_call.on_enable +         function="Profile.EnableShowOnMap" /> +    </menu_item_call> +    <menu_item_call       label="Pay"       layout="topleft"       name="pay"> diff --git a/indra/newview/skins/default/xui/en/panel_bottomtray.xml b/indra/newview/skins/default/xui/en/panel_bottomtray.xml index e70a0512d6..58c5c11e51 100644 --- a/indra/newview/skins/default/xui/en/panel_bottomtray.xml +++ b/indra/newview/skins/default/xui/en/panel_bottomtray.xml @@ -74,12 +74,15 @@             name="talk"             top="5"            width="105"> +            <!-- do not remove halign attribute with default value. otherwise it can't be overridden in other locales. +             & pad_right is default value for long label which can be right aligned. See EXT-6318 -->    <speak_button -    halign="left" +    halign="center"      name="speak_btn"      label="Speak"      label_selected="Speak" -    pad_left="12" +    pad_right="22" +    use_ellipses="true"      />                <show_button>                    <show_button.init_callback diff --git a/indra/newview/skins/default/xui/en/panel_prim_media_controls.xml b/indra/newview/skins/default/xui/en/panel_prim_media_controls.xml index 6b5f0c3896..6bf00373ea 100644 --- a/indra/newview/skins/default/xui/en/panel_prim_media_controls.xml +++ b/indra/newview/skins/default/xui/en/panel_prim_media_controls.xml @@ -1,7 +1,7 @@  <?xml version="1.0" encoding="utf-8" standalone="yes" ?>  <panel  	follows="left|right|top|bottom" -	name="MediaControlsPanel" +	name="MediaControls"  	background_visible="false"  	height="200"  	layout="topleft" diff --git a/indra/newview/skins/default/xui/en/panel_profile.xml b/indra/newview/skins/default/xui/en/panel_profile.xml index 9fcabc7722..30191aecb6 100644 --- a/indra/newview/skins/default/xui/en/panel_profile.xml +++ b/indra/newview/skins/default/xui/en/panel_profile.xml @@ -311,7 +311,7 @@           height="23"           label="Add Friend"           layout="topleft" -         left="1" +         left="2"           mouse_opaque="false"           name="add_friend"           pad_left="1"  @@ -319,7 +319,7 @@           tool_tip="Offer friendship to the Resident"           top="5"           use_ellipses="true" -         width="105" /> +         width="117" />          <button           follows="bottom|left"           height="23" @@ -328,8 +328,8 @@           name="im"           tool_tip="Open instant message session"           top="5" -         left_pad="0" -         width="19" /> +         left_pad="1" +         width="21" />          <button           follows="bottom|left"           height="23" @@ -337,26 +337,12 @@           layout="topleft"           name="call"           tool_tip="Call this Resident" -         left_pad="0" +         left_pad="1"           pad_left="1"            pad_right="1"           top="5"           use_ellipses="true" -         width="48" /> -        <button -         enabled="false" -         follows="bottom|left" -         height="23" -         label="Map" -         layout="topleft" -         name="show_on_map_btn" -         pad_left="1"  -         pad_right="1" -         tool_tip="Show the Resident on the map" -         top="5" -         left_pad="0" -         use_ellipses="true" -         width="33" /> +         width="51" />          <button           follows="bottom|left"           height="23" @@ -364,12 +350,12 @@           layout="topleft"           name="teleport"           tool_tip="Offer teleport" -         left_pad="0" +         left_pad="1"           pad_left="1"            pad_right="1"           top="5"           use_ellipses="true" -         width="81" /> +         width="92" />          <button           follows="bottom|right"           height="23" diff --git a/indra/newview/skins/default/xui/en/widgets/chat_history.xml b/indra/newview/skins/default/xui/en/widgets/chat_history.xml index ef885e8045..aa3ea736b8 100644 --- a/indra/newview/skins/default/xui/en/widgets/chat_history.xml +++ b/indra/newview/skins/default/xui/en/widgets/chat_history.xml @@ -2,6 +2,7 @@  <chat_history    message_header="panel_chat_header.xml"    message_separator="panel_chat_separator.xml" +  message_plaintext_separator="panel_chat_plaintext_separator.xml"    left_text_pad="10"    right_text_pad="15"    left_widget_pad="0" | 
