Skip to content
Snippets Groups Projects
Commit 2d113743 authored by Mnikolenko Productengine's avatar Mnikolenko Productengine
Browse files

SL-14504 FIXED Classified links always launch your Profile Classifieds

parent d6480e2b
No related branches found
No related tags found
No related merge requests found
...@@ -433,6 +433,7 @@ set(viewer_SOURCE_FILES ...@@ -433,6 +433,7 @@ set(viewer_SOURCE_FILES
llpanelavatar.cpp llpanelavatar.cpp
llpanelavatartag.cpp llpanelavatartag.cpp
llpanelblockedlist.cpp llpanelblockedlist.cpp
llpanelclassified.cpp
llpanelcontents.cpp llpanelcontents.cpp
llpaneleditsky.cpp llpaneleditsky.cpp
llpaneleditwater.cpp llpaneleditwater.cpp
...@@ -1057,6 +1058,7 @@ set(viewer_HEADER_FILES ...@@ -1057,6 +1058,7 @@ set(viewer_HEADER_FILES
llpanelavatar.h llpanelavatar.h
llpanelavatartag.h llpanelavatartag.h
llpanelblockedlist.h llpanelblockedlist.h
llpanelclassified.h
llpanelcontents.h llpanelcontents.h
llpaneleditsky.h llpaneleditsky.h
llpaneleditwater.h llpaneleditwater.h
......
/**
* @file llpanelclassified.cpp
* @brief LLPanelClassifiedInfo class implementation
*
* $LicenseInfo:firstyear=2021&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2021, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
// Display of a classified used both for the global view in the
// Find directory, and also for each individual user's classified in their
// profile.
#include "llviewerprecompiledheaders.h"
#include "llpanelclassified.h"
#include "lldispatcher.h"
#include "llfloaterreg.h"
#include "llparcel.h"
#include "llagent.h"
#include "llclassifiedflags.h"
#include "lliconctrl.h"
#include "lltexturectrl.h"
#include "llfloaterworldmap.h"
#include "llviewergenericmessage.h" // send_generic_message
#include "llviewerregion.h"
#include "llscrollcontainer.h"
#include "llcorehttputil.h"
//static
LLPanelClassifiedInfo::panel_list_t LLPanelClassifiedInfo::sAllPanels;
static LLPanelInjector<LLPanelClassifiedInfo> t_panel_panel_classified_info("panel_classified_info");
// "classifiedclickthrough"
// strings[0] = classified_id
// strings[1] = teleport_clicks
// strings[2] = map_clicks
// strings[3] = profile_clicks
class LLDispatchClassifiedClickThrough : public LLDispatchHandler
{
public:
virtual bool operator()(
const LLDispatcher* dispatcher,
const std::string& key,
const LLUUID& invoice,
const sparam_t& strings)
{
if (strings.size() != 4) return false;
LLUUID classified_id(strings[0]);
S32 teleport_clicks = atoi(strings[1].c_str());
S32 map_clicks = atoi(strings[2].c_str());
S32 profile_clicks = atoi(strings[3].c_str());
LLPanelClassifiedInfo::setClickThrough(
classified_id, teleport_clicks, map_clicks, profile_clicks, false);
return true;
}
};
static LLDispatchClassifiedClickThrough sClassifiedClickThrough;
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
LLPanelClassifiedInfo::LLPanelClassifiedInfo()
: LLPanel()
, mInfoLoaded(false)
, mScrollingPanel(NULL)
, mScrollContainer(NULL)
, mScrollingPanelMinHeight(0)
, mScrollingPanelWidth(0)
, mSnapshotStreched(false)
, mTeleportClicksOld(0)
, mMapClicksOld(0)
, mProfileClicksOld(0)
, mTeleportClicksNew(0)
, mMapClicksNew(0)
, mProfileClicksNew(0)
, mSnapshotCtrl(NULL)
{
sAllPanels.push_back(this);
}
LLPanelClassifiedInfo::~LLPanelClassifiedInfo()
{
sAllPanels.remove(this);
}
BOOL LLPanelClassifiedInfo::postBuild()
{
childSetAction("show_on_map_btn", boost::bind(&LLPanelClassifiedInfo::onMapClick, this));
childSetAction("teleport_btn", boost::bind(&LLPanelClassifiedInfo::onTeleportClick, this));
mScrollingPanel = getChild<LLPanel>("scroll_content_panel");
mScrollContainer = getChild<LLScrollContainer>("profile_scroll");
mScrollingPanelMinHeight = mScrollContainer->getScrolledViewRect().getHeight();
mScrollingPanelWidth = mScrollingPanel->getRect().getWidth();
mSnapshotCtrl = getChild<LLTextureCtrl>("classified_snapshot");
mSnapshotRect = getDefaultSnapshotRect();
return TRUE;
}
void LLPanelClassifiedInfo::reshape(S32 width, S32 height, BOOL called_from_parent /* = TRUE */)
{
LLPanel::reshape(width, height, called_from_parent);
if (!mScrollContainer || !mScrollingPanel)
return;
static LLUICachedControl<S32> scrollbar_size ("UIScrollbarSize", 0);
S32 scroll_height = mScrollContainer->getRect().getHeight();
if (mScrollingPanelMinHeight >= scroll_height)
{
mScrollingPanel->reshape(mScrollingPanelWidth, mScrollingPanelMinHeight);
}
else
{
mScrollingPanel->reshape(mScrollingPanelWidth + scrollbar_size, scroll_height);
}
mSnapshotRect = getDefaultSnapshotRect();
stretchSnapshot();
}
void LLPanelClassifiedInfo::onOpen(const LLSD& key)
{
LLUUID avatar_id = key["classified_creator_id"];
if(avatar_id.isNull())
{
return;
}
if(getAvatarId().notNull())
{
LLAvatarPropertiesProcessor::getInstance()->removeObserver(getAvatarId(), this);
}
setAvatarId(avatar_id);
resetData();
resetControls();
scrollToTop();
setClassifiedId(key["classified_id"]);
setClassifiedName(key["classified_name"]);
setDescription(key["classified_desc"]);
setSnapshotId(key["classified_snapshot_id"]);
setFromSearch(key["from_search"]);
LL_INFOS() << "Opening classified [" << getClassifiedName() << "] (" << getClassifiedId() << ")" << LL_ENDL;
LLAvatarPropertiesProcessor::getInstance()->addObserver(getAvatarId(), this);
LLAvatarPropertiesProcessor::getInstance()->sendClassifiedInfoRequest(getClassifiedId());
gGenericDispatcher.addHandler("classifiedclickthrough", &sClassifiedClickThrough);
if (gAgent.getRegion())
{
// While we're at it let's get the stats from the new table if that
// capability exists.
std::string url = gAgent.getRegion()->getCapability("SearchStatRequest");
if (!url.empty())
{
LL_INFOS() << "Classified stat request via capability" << LL_ENDL;
LLSD body;
LLUUID classifiedId = getClassifiedId();
body["classified_id"] = classifiedId;
LLCoreHttpUtil::HttpCoroutineAdapter::callbackHttpPost(url, body,
boost::bind(&LLPanelClassifiedInfo::handleSearchStatResponse, classifiedId, _1));
}
}
// Update classified click stats.
// *TODO: Should we do this when opening not from search?
sendClickMessage("profile");
setInfoLoaded(false);
}
/*static*/
void LLPanelClassifiedInfo::handleSearchStatResponse(LLUUID classifiedId, LLSD result)
{
S32 teleport = result["teleport_clicks"].asInteger();
S32 map = result["map_clicks"].asInteger();
S32 profile = result["profile_clicks"].asInteger();
S32 search_teleport = result["search_teleport_clicks"].asInteger();
S32 search_map = result["search_map_clicks"].asInteger();
S32 search_profile = result["search_profile_clicks"].asInteger();
LLPanelClassifiedInfo::setClickThrough(classifiedId,
teleport + search_teleport,
map + search_map,
profile + search_profile,
true);
}
void LLPanelClassifiedInfo::processProperties(void* data, EAvatarProcessorType type)
{
if(APT_CLASSIFIED_INFO == type)
{
LLAvatarClassifiedInfo* c_info = static_cast<LLAvatarClassifiedInfo*>(data);
if(c_info && getClassifiedId() == c_info->classified_id)
{
setClassifiedName(c_info->name);
setDescription(c_info->description);
setSnapshotId(c_info->snapshot_id);
setParcelId(c_info->parcel_id);
setPosGlobal(c_info->pos_global);
setSimName(c_info->sim_name);
setClassifiedLocation(createLocationText(c_info->parcel_name, c_info->sim_name, c_info->pos_global));
getChild<LLUICtrl>("category")->setValue(LLClassifiedInfo::sCategories[c_info->category]);
static std::string mature_str = getString("type_mature");
static std::string pg_str = getString("type_pg");
static LLUIString price_str = getString("l$_price");
static std::string date_fmt = getString("date_fmt");
bool mature = is_cf_mature(c_info->flags);
getChild<LLUICtrl>("content_type")->setValue(mature ? mature_str : pg_str);
getChild<LLIconCtrl>("content_type_moderate")->setVisible(mature);
getChild<LLIconCtrl>("content_type_general")->setVisible(!mature);
std::string auto_renew_str = is_cf_auto_renew(c_info->flags) ?
getString("auto_renew_on") : getString("auto_renew_off");
getChild<LLUICtrl>("auto_renew")->setValue(auto_renew_str);
price_str.setArg("[PRICE]", llformat("%d", c_info->price_for_listing));
getChild<LLUICtrl>("price_for_listing")->setValue(LLSD(price_str));
std::string date_str = date_fmt;
LLStringUtil::format(date_str, LLSD().with("datetime", (S32) c_info->creation_date));
getChild<LLUICtrl>("creation_date")->setValue(date_str);
setInfoLoaded(true);
LLAvatarPropertiesProcessor::getInstance()->removeObserver(getAvatarId(), this);
}
}
}
void LLPanelClassifiedInfo::resetData()
{
setClassifiedName(LLStringUtil::null);
setDescription(LLStringUtil::null);
setClassifiedLocation(LLStringUtil::null);
setClassifiedId(LLUUID::null);
setSnapshotId(LLUUID::null);
setPosGlobal(LLVector3d::zero);
setParcelId(LLUUID::null);
setSimName(LLStringUtil::null);
setFromSearch(false);
// reset click stats
mTeleportClicksOld = 0;
mMapClicksOld = 0;
mProfileClicksOld = 0;
mTeleportClicksNew = 0;
mMapClicksNew = 0;
mProfileClicksNew = 0;
getChild<LLUICtrl>("category")->setValue(LLStringUtil::null);
getChild<LLUICtrl>("content_type")->setValue(LLStringUtil::null);
getChild<LLUICtrl>("click_through_text")->setValue(LLStringUtil::null);
getChild<LLUICtrl>("price_for_listing")->setValue(LLStringUtil::null);
getChild<LLUICtrl>("auto_renew")->setValue(LLStringUtil::null);
getChild<LLUICtrl>("creation_date")->setValue(LLStringUtil::null);
getChild<LLUICtrl>("click_through_text")->setValue(LLStringUtil::null);
getChild<LLIconCtrl>("content_type_moderate")->setVisible(FALSE);
getChild<LLIconCtrl>("content_type_general")->setVisible(FALSE);
}
void LLPanelClassifiedInfo::resetControls()
{
bool is_self = getAvatarId() == gAgent.getID();
getChildView("edit_btn")->setEnabled(is_self);
getChildView("edit_btn")->setVisible( is_self);
getChildView("price_layout_panel")->setVisible( is_self);
getChildView("clickthrough_layout_panel")->setVisible( is_self);
}
void LLPanelClassifiedInfo::setClassifiedName(const std::string& name)
{
getChild<LLUICtrl>("classified_name")->setValue(name);
}
std::string LLPanelClassifiedInfo::getClassifiedName()
{
return getChild<LLUICtrl>("classified_name")->getValue().asString();
}
void LLPanelClassifiedInfo::setDescription(const std::string& desc)
{
getChild<LLUICtrl>("classified_desc")->setValue(desc);
}
std::string LLPanelClassifiedInfo::getDescription()
{
return getChild<LLUICtrl>("classified_desc")->getValue().asString();
}
void LLPanelClassifiedInfo::setClassifiedLocation(const std::string& location)
{
getChild<LLUICtrl>("classified_location")->setValue(location);
}
std::string LLPanelClassifiedInfo::getClassifiedLocation()
{
return getChild<LLUICtrl>("classified_location")->getValue().asString();
}
void LLPanelClassifiedInfo::setSnapshotId(const LLUUID& id)
{
mSnapshotCtrl->setValue(id);
mSnapshotStreched = false;
}
void LLPanelClassifiedInfo::draw()
{
LLPanel::draw();
// Stretch in draw because it takes some time to load a texture,
// going to try to stretch snapshot until texture is loaded
if(!mSnapshotStreched)
{
stretchSnapshot();
}
}
LLUUID LLPanelClassifiedInfo::getSnapshotId()
{
return getChild<LLUICtrl>("classified_snapshot")->getValue().asUUID();
}
// static
void LLPanelClassifiedInfo::setClickThrough(
const LLUUID& classified_id,
S32 teleport,
S32 map,
S32 profile,
bool from_new_table)
{
LL_INFOS() << "Click-through data for classified " << classified_id << " arrived: ["
<< teleport << ", " << map << ", " << profile << "] ("
<< (from_new_table ? "new" : "old") << ")" << LL_ENDL;
for (panel_list_t::iterator iter = sAllPanels.begin(); iter != sAllPanels.end(); ++iter)
{
LLPanelClassifiedInfo* self = *iter;
if (self->getClassifiedId() != classified_id)
{
continue;
}
// *HACK: Skip LLPanelClassifiedEdit instances: they don't display clicks data.
// Those instances should not be in the list at all.
if (typeid(*self) != typeid(LLPanelClassifiedInfo))
{
continue;
}
LL_INFOS() << "Updating classified info panel" << LL_ENDL;
// We need to check to see if the data came from the new stat_table
// or the old classified table. We also need to cache the data from
// the two separate sources so as to display the aggregate totals.
if (from_new_table)
{
self->mTeleportClicksNew = teleport;
self->mMapClicksNew = map;
self->mProfileClicksNew = profile;
}
else
{
self->mTeleportClicksOld = teleport;
self->mMapClicksOld = map;
self->mProfileClicksOld = profile;
}
static LLUIString ct_str = self->getString("click_through_text_fmt");
ct_str.setArg("[TELEPORT]", llformat("%d", self->mTeleportClicksNew + self->mTeleportClicksOld));
ct_str.setArg("[MAP]", llformat("%d", self->mMapClicksNew + self->mMapClicksOld));
ct_str.setArg("[PROFILE]", llformat("%d", self->mProfileClicksNew + self->mProfileClicksOld));
self->getChild<LLUICtrl>("click_through_text")->setValue(ct_str.getString());
// *HACK: remove this when there is enough room for click stats in the info panel
self->getChildView("click_through_text")->setToolTip(ct_str.getString());
LL_INFOS() << "teleport: " << llformat("%d", self->mTeleportClicksNew + self->mTeleportClicksOld)
<< ", map: " << llformat("%d", self->mMapClicksNew + self->mMapClicksOld)
<< ", profile: " << llformat("%d", self->mProfileClicksNew + self->mProfileClicksOld)
<< LL_ENDL;
}
}
// static
std::string LLPanelClassifiedInfo::createLocationText(
const std::string& original_name,
const std::string& sim_name,
const LLVector3d& pos_global)
{
std::string location_text;
location_text.append(original_name);
if (!sim_name.empty())
{
if (!location_text.empty())
location_text.append(", ");
location_text.append(sim_name);
}
if (!location_text.empty())
location_text.append(" ");
if (!pos_global.isNull())
{
S32 region_x = ll_round((F32)pos_global.mdV[VX]) % REGION_WIDTH_UNITS;
S32 region_y = ll_round((F32)pos_global.mdV[VY]) % REGION_WIDTH_UNITS;
S32 region_z = ll_round((F32)pos_global.mdV[VZ]);
location_text.append(llformat(" (%d, %d, %d)", region_x, region_y, region_z));
}
return location_text;
}
void LLPanelClassifiedInfo::stretchSnapshot()
{
// *NOTE dzaporozhan
// Could be moved to LLTextureCtrl
LLViewerFetchedTexture* texture = mSnapshotCtrl->getTexture();
if(!texture)
{
return;
}
if(0 == texture->getOriginalWidth() || 0 == texture->getOriginalHeight())
{
// looks like texture is not loaded yet
return;
}
LLRect rc = mSnapshotRect;
// *HACK dzaporozhan
// LLTextureCtrl uses BTN_HEIGHT_SMALL as bottom for texture which causes
// drawn texture to be smaller than expected. (see LLTextureCtrl::draw())
// Lets increase texture height to force texture look as expected.
rc.mBottom -= BTN_HEIGHT_SMALL;
F32 t_width = texture->getFullWidth();
F32 t_height = texture->getFullHeight();
F32 ratio = llmin<F32>( (rc.getWidth() / t_width), (rc.getHeight() / t_height) );
t_width *= ratio;
t_height *= ratio;
rc.setCenterAndSize(rc.getCenterX(), rc.getCenterY(), llfloor(t_width), llfloor(t_height));
mSnapshotCtrl->setShape(rc);
mSnapshotStreched = true;
}
LLRect LLPanelClassifiedInfo::getDefaultSnapshotRect()
{
// Using scroll container makes getting default rect a hard task
// because rect in postBuild() and in first reshape() is not the same.
// Using snapshot_panel makes it easier to reshape snapshot.
return getChild<LLUICtrl>("snapshot_panel")->getLocalRect();
}
void LLPanelClassifiedInfo::scrollToTop()
{
LLScrollContainer* scrollContainer = findChild<LLScrollContainer>("profile_scroll");
if (scrollContainer)
scrollContainer->goToTop();
}
// static
// *TODO: move out of the panel
void LLPanelClassifiedInfo::sendClickMessage(
const std::string& type,
bool from_search,
const LLUUID& classified_id,
const LLUUID& parcel_id,
const LLVector3d& global_pos,
const std::string& sim_name)
{
if (gAgent.getRegion())
{
// You're allowed to click on your own ads to reassure yourself
// that the system is working.
LLSD body;
body["type"] = type;
body["from_search"] = from_search;
body["classified_id"] = classified_id;
body["parcel_id"] = parcel_id;
body["dest_pos_global"] = global_pos.getValue();
body["region_name"] = sim_name;
std::string url = gAgent.getRegion()->getCapability("SearchStatTracking");
LL_INFOS() << "Sending click msg via capability (url=" << url << ")" << LL_ENDL;
LL_INFOS() << "body: [" << body << "]" << LL_ENDL;
LLCoreHttpUtil::HttpCoroutineAdapter::messageHttpPost(url, body,
"SearchStatTracking Click report sent.", "SearchStatTracking Click report NOT sent.");
}
}
void LLPanelClassifiedInfo::sendClickMessage(const std::string& type)
{
sendClickMessage(
type,
fromSearch(),
getClassifiedId(),
getParcelId(),
getPosGlobal(),
getSimName());
}
void LLPanelClassifiedInfo::onMapClick()
{
sendClickMessage("map");
LLFloaterWorldMap::getInstance()->trackLocation(getPosGlobal());
LLFloaterReg::showInstance("world_map", "center");
}
void LLPanelClassifiedInfo::onTeleportClick()
{
if (!getPosGlobal().isExactlyZero())
{
sendClickMessage("teleport");
gAgent.teleportViaLocation(getPosGlobal());
LLFloaterWorldMap::getInstance()->trackLocation(getPosGlobal());
}
}
//EOF
/**
* @file llpanelclassified.h
* @brief LLPanelClassifiedInfo class definition
*
* $LicenseInfo:firstyear=2021&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2021, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
// Display of a classified used both for the global view in the
// Find directory, and also for each individual user's classified in their
// profile.
#ifndef LL_LLPANELCLASSIFIED_H
#define LL_LLPANELCLASSIFIED_H
#include "llavatarpropertiesprocessor.h"
#include "llclassifiedinfo.h"
#include "llfloater.h"
#include "llpanel.h"
#include "llrect.h"
class LLScrollContainer;
class LLTextureCtrl;
class LLPanelClassifiedInfo : public LLPanel, public LLAvatarPropertiesObserver
{
LOG_CLASS(LLPanelClassifiedInfo);
public:
LLPanelClassifiedInfo();
virtual ~LLPanelClassifiedInfo();
/*virtual*/ void onOpen(const LLSD& key);
/*virtual*/ BOOL postBuild();
/*virtual*/ void processProperties(void* data, EAvatarProcessorType type);
void setAvatarId(const LLUUID& avatar_id) { mAvatarId = avatar_id; }
LLUUID& getAvatarId() { return mAvatarId; }
void setSnapshotId(const LLUUID& id);
LLUUID getSnapshotId();
void setClassifiedId(const LLUUID& id) { mClassifiedId = id; }
LLUUID& getClassifiedId() { return mClassifiedId; }
void setClassifiedName(const std::string& name);
std::string getClassifiedName();
void setDescription(const std::string& desc);
std::string getDescription();
void setClassifiedLocation(const std::string& location);
std::string getClassifiedLocation();
void setPosGlobal(const LLVector3d& pos) { mPosGlobal = pos; }
LLVector3d& getPosGlobal() { return mPosGlobal; }
void setParcelId(const LLUUID& id) { mParcelId = id; }
LLUUID getParcelId() { return mParcelId; }
void setSimName(const std::string& sim_name) { mSimName = sim_name; }
std::string getSimName() { return mSimName; }
void setFromSearch(bool val) { mFromSearch = val; }
bool fromSearch() { return mFromSearch; }
bool getInfoLoaded() { return mInfoLoaded; }
void setInfoLoaded(bool loaded) { mInfoLoaded = loaded; }
static void setClickThrough(
const LLUUID& classified_id,
S32 teleport,
S32 map,
S32 profile,
bool from_new_table);
static void sendClickMessage(
const std::string& type,
bool from_search,
const LLUUID& classified_id,
const LLUUID& parcel_id,
const LLVector3d& global_pos,
const std::string& sim_name);
/*virtual*/ void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE);
/*virtual*/ void draw();
protected:
virtual void resetData();
virtual void resetControls();
static std::string createLocationText(
const std::string& original_name,
const std::string& sim_name,
const LLVector3d& pos_global);
void stretchSnapshot();
void sendClickMessage(const std::string& type);
LLRect getDefaultSnapshotRect();
void scrollToTop();
void onMapClick();
void onTeleportClick();
bool mSnapshotStreched;
LLRect mSnapshotRect;
LLTextureCtrl* mSnapshotCtrl;
private:
LLUUID mAvatarId;
LLUUID mClassifiedId;
LLVector3d mPosGlobal;
LLUUID mParcelId;
std::string mSimName;
bool mFromSearch;
bool mInfoLoaded;
LLScrollContainer* mScrollContainer;
LLPanel* mScrollingPanel;
S32 mScrollingPanelMinHeight;
S32 mScrollingPanelWidth;
// Needed for stat tracking
S32 mTeleportClicksOld;
S32 mMapClicksOld;
S32 mProfileClicksOld;
S32 mTeleportClicksNew;
S32 mMapClicksNew;
S32 mProfileClicksNew;
static void handleSearchStatResponse(LLUUID classifiedId, LLSD result);
typedef std::list<LLPanelClassifiedInfo*> panel_list_t;
static panel_list_t sAllPanels;
};
#endif // LL_LLPANELCLASSIFIED_H
...@@ -63,6 +63,7 @@ ...@@ -63,6 +63,7 @@
#include "llpanelprofilepicks.h" #include "llpanelprofilepicks.h"
#include "lltrans.h" #include "lltrans.h"
#include "llviewercontrol.h" #include "llviewercontrol.h"
#include "llviewermenu.h" //is_agent_mappable
#include "llvoiceclient.h" #include "llvoiceclient.h"
#include "llweb.h" #include "llweb.h"
......
...@@ -37,6 +37,7 @@ ...@@ -37,6 +37,7 @@
#include "llcorehttputil.h" #include "llcorehttputil.h"
#include "lldispatcher.h" #include "lldispatcher.h"
#include "llfloaterreg.h" #include "llfloaterreg.h"
#include "llfloatersidepanelcontainer.h"
#include "llfloaterworldmap.h" #include "llfloaterworldmap.h"
#include "lliconctrl.h" #include "lliconctrl.h"
#include "lllineeditor.h" #include "lllineeditor.h"
...@@ -70,13 +71,16 @@ LLPanelProfileClassified::panel_list_t LLPanelProfileClassified::sAllPanels; ...@@ -70,13 +71,16 @@ LLPanelProfileClassified::panel_list_t LLPanelProfileClassified::sAllPanels;
static LLPanelInjector<LLPanelProfileClassifieds> t_panel_profile_classifieds("panel_profile_classifieds"); static LLPanelInjector<LLPanelProfileClassifieds> t_panel_profile_classifieds("panel_profile_classifieds");
static LLPanelInjector<LLPanelProfileClassified> t_panel_profile_classified("panel_profile_classified"); static LLPanelInjector<LLPanelProfileClassified> t_panel_profile_classified("panel_profile_classified");
class LLClassifiedHandler : public LLCommandHandler class LLClassifiedHandler : public LLCommandHandler, public LLAvatarPropertiesObserver
{ {
public: public:
// throttle calls from untrusted browsers // throttle calls from untrusted browsers
LLClassifiedHandler() : LLCommandHandler("classified", UNTRUSTED_THROTTLE) {} LLClassifiedHandler() : LLCommandHandler("classified", UNTRUSTED_THROTTLE) {}
bool handle(const LLSD& params, const LLSD& query_map, LLMediaCtrl* web) std::set<LLUUID> mClassifiedIds;
std::string mRequestVerb;
bool handle(const LLSD& params, const LLSD& query_map, LLMediaCtrl* web)
{ {
if (!LLUI::getInstance()->mSettingGroups["config"]->getBOOL("EnableClassifieds")) if (!LLUI::getInstance()->mSettingGroups["config"]->getBOOL("EnableClassifieds"))
{ {
...@@ -109,7 +113,10 @@ class LLClassifiedHandler : public LLCommandHandler ...@@ -109,7 +113,10 @@ class LLClassifiedHandler : public LLCommandHandler
const std::string verb = params[1].asString(); const std::string verb = params[1].asString();
if (verb == "about") if (verb == "about")
{ {
LLAvatarActions::showClassified(gAgent.getID(), classified_id, false); mRequestVerb = verb;
mClassifiedIds.insert(classified_id);
LLAvatarPropertiesProcessor::getInstance()->addObserver(LLUUID(), this);
LLAvatarPropertiesProcessor::getInstance()->sendClassifiedInfoRequest(classified_id);
return true; return true;
} }
else if (verb == "edit") else if (verb == "edit")
...@@ -120,6 +127,53 @@ class LLClassifiedHandler : public LLCommandHandler ...@@ -120,6 +127,53 @@ class LLClassifiedHandler : public LLCommandHandler
return false; return false;
} }
void openClassified(LLAvatarClassifiedInfo* c_info)
{
if (mRequestVerb == "about")
{
if (c_info->creator_id == gAgent.getID())
{
LLAvatarActions::showClassified(gAgent.getID(), c_info->classified_id, false);
}
else
{
LLSD params;
params["id"] = c_info->creator_id;
params["open_tab_name"] = "panel_picks";
params["show_tab_panel"] = "classified_details";
params["classified_id"] = c_info->classified_id;
params["classified_creator_id"] = c_info->creator_id;
params["classified_snapshot_id"] = c_info->snapshot_id;
params["classified_name"] = c_info->name;
params["classified_desc"] = c_info->description;
params["from_search"] = true;
LLFloaterSidePanelContainer::showPanel("picks", params);
}
}
}
void processProperties(void* data, EAvatarProcessorType type)
{
if (APT_CLASSIFIED_INFO != type)
{
return;
}
// is this the classified that we asked for?
LLAvatarClassifiedInfo* c_info = static_cast<LLAvatarClassifiedInfo*>(data);
if (!c_info || mClassifiedIds.find(c_info->classified_id) == mClassifiedIds.end())
{
return;
}
// open the detail side tray for this classified
openClassified(c_info);
// remove our observer now that we're done
mClassifiedIds.erase(c_info->classified_id);
LLAvatarPropertiesProcessor::getInstance()->removeObserver(LLUUID(), this);
}
}; };
LLClassifiedHandler gClassifiedHandler; LLClassifiedHandler gClassifiedHandler;
......
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<floater
positioning="cascading"
can_close="true"
can_resize="false"
height="572"
help_topic="sidebar_me"
min_width="333"
min_height="440"
name="floater_picks"
save_rect="true"
save_visibility="false"
reuse_instance="true"
title="Picks"
width="333" >
<panel
class="panel_classified_info"
name="main_panel"
filename="panel_classified_info.xml"
follows="all"/>
</floater>
...@@ -38,28 +38,15 @@ ...@@ -38,28 +38,15 @@
name="auto_renew_off"> name="auto_renew_off">
Disabled Disabled
</panel.string> </panel.string>
<button
follows="top|left"
height="24"
image_hover_unselected="BackButton_Over"
image_pressed="BackButton_Press"
image_unselected="BackButton_Off"
layout="topleft"
name="back_btn"
left="10"
tab_stop="false"
top="2"
width="30"
use_draw_context_alpha="false" />
<text <text
follows="top|left|right" follows="top|left|right"
font="SansSerifHugeBold" font="SansSerifHugeBold"
height="26" height="26"
layout="topleft" layout="topleft"
left_pad="4" left="12"
name="title" name="title"
text_color="LtGray" text_color="LtGray"
top="0" top="2"
value="Classified Info" value="Classified Info"
use_ellipses="true" use_ellipses="true"
width="275" /> width="275" />
...@@ -420,7 +407,7 @@ ...@@ -420,7 +407,7 @@
height="23" height="23"
label="Teleport" label="Teleport"
layout="topleft" layout="topleft"
left="0" left="2"
name="teleport_btn" name="teleport_btn"
top="0" top="0"
width="101" /> width="101" />
...@@ -443,24 +430,6 @@ ...@@ -443,24 +430,6 @@
top="0" top="0"
width="100" /> width="100" />
</layout_panel> </layout_panel>
<layout_panel
follows="bottom|left|right"
height="23"
layout="bottomleft"
left_pad="3"
name="edit_btn_lp"
auto_resize="true"
width="101">
<button
follows="bottom|left|right"
height="23"
label="Edit"
layout="topleft"
name="edit_btn"
top="0"
width="101" />
</layout_panel>
</layout_stack> </layout_stack>
</panel> </panel>
</panel> </panel>
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment