summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--indra/llui/llnotifications.cpp25
-rw-r--r--indra/llui/llnotifications.h10
-rw-r--r--indra/newview/lltoastnotifypanel.cpp89
-rw-r--r--indra/newview/lltoastnotifypanel.h7
-rw-r--r--indra/newview/llviewermessage.cpp20
-rw-r--r--indra/newview/llviewermessage.h2
6 files changed, 148 insertions, 5 deletions
diff --git a/indra/llui/llnotifications.cpp b/indra/llui/llnotifications.cpp
index 5816cef6af..7b8970a153 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"];
@@ -563,7 +570,9 @@ void LLNotification::respond(const LLSD& response)
// 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 +606,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();
diff --git a/indra/llui/llnotifications.h b/indra/llui/llnotifications.h
index 8d993b71d7..262633206b 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;
}
};
@@ -344,6 +347,7 @@ private:
bool mIgnored;
ENotificationPriority mPriority;
LLNotificationFormPtr mForm;
+ void* mResponderObj;
// a reference to the template
LLNotificationTemplatePtr mTemplatep;
@@ -384,6 +388,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 +429,10 @@ public:
void respond(const LLSD& sd);
+ void* getResponder() { return mResponderObj; }
+
+ void setResponder(void* responder) { mResponderObj = responder; }
+
void setIgnored(bool ignore);
bool isCancelled() const
diff --git a/indra/newview/lltoastnotifypanel.cpp b/indra/newview/lltoastnotifypanel.cpp
index 9108cc9889..7c5af4a8bb 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
@@ -185,6 +186,8 @@ mCloseNotificationOnDestroy(true)
// 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
@@ -334,6 +337,63 @@ 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;
+}
+
+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();
+
+ disable_button_map_t::const_iterator it;
+ disable_button_map_t::const_iterator it_end;
+
+ if("UserGiveItem" == notification_name)
+ {
+ it = user_give_item_disable_map.find(button_name);
+ it_end = user_give_item_disable_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)
{
@@ -346,8 +406,33 @@ 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)
+ {
+ self->disableButtons(self->mNotification->getName(), 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);
+ }
}
diff --git a/indra/newview/lltoastnotifypanel.h b/indra/newview/lltoastnotifypanel.h
index 9c90a4dfa4..5c83a893f0 100644
--- a/indra/newview/lltoastnotifypanel.h
+++ b/indra/newview/lltoastnotifypanel.h
@@ -85,6 +85,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
diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp
index 361f4e2326..de92e5f2ae 100644
--- a/indra/newview/llviewermessage.cpp
+++ b/indra/newview/llviewermessage.cpp
@@ -1081,6 +1081,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;
@@ -1570,7 +1585,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";
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;