summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrey Kleshchev <andreykproductengine@lindenlab.com>2022-04-09 00:57:19 +0300
committerAndrey Kleshchev <andreykproductengine@lindenlab.com>2022-04-09 00:57:19 +0300
commit285e36b57ea895f660f06095652b8cf03b7cbc09 (patch)
tree2c591fd818882a3c2a6d454ebf6801c698f25866
parent2f776a38af873163d6b5d5e030ce4b57a3e10e93 (diff)
SL-15312 Legacy profiles remake #3
-rw-r--r--indra/newview/llpanelprofile.cpp326
-rw-r--r--indra/newview/llpanelprofile.h15
-rw-r--r--indra/newview/llviewertexturelist.cpp1
-rw-r--r--indra/newview/skins/default/xui/en/menu_profile_other.xml31
-rw-r--r--indra/newview/skins/default/xui/en/menu_profile_self.xml74
-rw-r--r--indra/newview/skins/default/xui/en/panel_profile_secondlife.xml4
6 files changed, 337 insertions, 114 deletions
diff --git a/indra/newview/llpanelprofile.cpp b/indra/newview/llpanelprofile.cpp
index adf5036498..53d0cbec9f 100644
--- a/indra/newview/llpanelprofile.cpp
+++ b/indra/newview/llpanelprofile.cpp
@@ -291,13 +291,7 @@ void put_avatar_properties_coro(std::string cap_url, LLUUID agent_id, LLSD data)
}
}
-enum EProfileImageType
-{
- PROFILE_IMAGE_SL,
- PROFILE_IMAGE_FL,
-};
-
-void post_profile_image_coro(std::string cap_url, EProfileImageType type, std::string path_to_image)
+LLUUID post_profile_image(std::string cap_url, const LLSD &first_data, std::string path_to_image, LLHandle<LLPanel> *handle)
{
LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID);
LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t
@@ -307,17 +301,6 @@ void post_profile_image_coro(std::string cap_url, EProfileImageType type, std::s
LLCore::HttpOptions::ptr_t httpOpts(new LLCore::HttpOptions);
httpOpts->setFollowRedirects(true);
-
- LLSD first_data;
- switch (type)
- {
- case PROFILE_IMAGE_SL:
- first_data["profile-image-asset"] = "sl_image_id";
- break;
- case PROFILE_IMAGE_FL:
- first_data["profile-image-asset"] = "fl_image_id";
- break;
- }
LLSD result = httpAdapter->postAndSuspend(httpRequest, cap_url, first_data, httpOpts, httpHeaders);
@@ -326,22 +309,21 @@ void post_profile_image_coro(std::string cap_url, EProfileImageType type, std::s
if (!status)
{
+ // todo: notification?
LL_WARNS("AvatarProperties") << "Failed to get uploader cap " << status.toString() << LL_ENDL;
- LLFile::remove(path_to_image);
- return;
+ return LLUUID::null;
}
if (!result.has("uploader"))
{
+ // todo: notification?
LL_WARNS("AvatarProperties") << "Failed to get uploader cap, response contains no data." << LL_ENDL;
- LLFile::remove(path_to_image);
- return;
+ return LLUUID::null;
}
std::string uploader_cap = result["uploader"].asString();
if (uploader_cap.empty())
{
LL_WARNS("AvatarProperties") << "Failed to get uploader cap, cap invalid." << LL_ENDL;
- LLFile::remove(path_to_image);
- return;
+ return LLUUID::null;
}
// Upload the image
@@ -356,8 +338,7 @@ void post_profile_image_coro(std::string cap_url, EProfileImageType type, std::s
if (!instream.is_open())
{
LL_WARNS("AvatarProperties") << "Failed to open file " << path_to_image << LL_ENDL;
- LLFile::remove(path_to_image);
- return;
+ return LLUUID::null;
}
length = instream.tellg();
}
@@ -371,11 +352,12 @@ void post_profile_image_coro(std::string cap_url, EProfileImageType type, std::s
httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
+ LL_WARNS("AvatarProperties") << result << LL_ENDL;
+
if (!status)
{
LL_WARNS("AvatarProperties") << "Failed to upload image " << status.toString() << LL_ENDL;
- LLFile::remove(path_to_image);
- return;
+ return LLUUID::null;
}
if (result["state"].asString() != "complete")
@@ -388,14 +370,62 @@ void post_profile_image_coro(std::string cap_url, EProfileImageType type, std::s
{
LL_WARNS("AvatarProperties") << "Failed to upload image " << result << LL_ENDL;
}
- LLFile::remove(path_to_image);
- return;
+ return LLUUID::null;
+ }
+
+ return result["new_asset"].asUUID();
+}
+
+enum EProfileImageType
+{
+ PROFILE_IMAGE_SL,
+ PROFILE_IMAGE_FL,
+};
+
+void post_profile_image_coro(std::string cap_url, EProfileImageType type, std::string path_to_image, LLHandle<LLPanel> *handle)
+{
+ LLSD data;
+ switch (type)
+ {
+ case PROFILE_IMAGE_SL:
+ data["profile-image-asset"] = "sl_image_id";
+ break;
+ case PROFILE_IMAGE_FL:
+ data["profile-image-asset"] = "fl_image_id";
+ break;
}
+ LLUUID result = post_profile_image(cap_url, data, path_to_image, handle);
+
+ // reset loading indicator
+ switch (type)
+ {
+ case PROFILE_IMAGE_SL:
+ if (!handle->isDead())
+ {
+ LLPanelProfileSecondLife* panel = static_cast<LLPanelProfileSecondLife*>(handle->get());
+ if (result.notNull())
+ {
+ panel->setProfileImageUploaded(result);
+ }
+ else
+ {
+ // failure, just stop progress indicator
+ panel->setProfileImageUploading(false);
+ }
+ }
+ break;
+ case PROFILE_IMAGE_FL:
+ // Todo: refresh the panel
+ break;
+ }
+
+ // Cleanup
LLFile::remove(path_to_image);
+ delete handle;
}
-void launch_profile_image_coro(EProfileImageType type, const std::string &file_path)
+void launch_profile_image_coro(EProfileImageType type, const std::string &file_path, LLHandle<LLPanel> *handle)
{
std::string cap_url = gAgent.getRegionCapability(PROFILE_IMAGE_UPLOAD_CAP);
if (!cap_url.empty())
@@ -410,7 +440,7 @@ void launch_profile_image_coro(EProfileImageType type, const std::string &file_p
if (LLViewerTextureList::createUploadFile(file_path, temp_file, codec, MAX_DIM))
{
LLCoros::instance().launch("postAgentUserImageCoro",
- boost::bind(post_profile_image_coro, cap_url, type, temp_file));
+ boost::bind(post_profile_image_coro, cap_url, type, temp_file, handle));
}
}
else
@@ -564,6 +594,7 @@ LLAgentHandler gAgentHandler;
LLPanelProfileSecondLife::LLPanelProfileSecondLife()
: LLPanelProfileTab()
, mAvatarNameCacheConnection()
+ , mWaitingForImageUpload(false)
{
}
@@ -583,8 +614,6 @@ LLPanelProfileSecondLife::~LLPanelProfileSecondLife()
{
mAvatarNameCacheConnection.disconnect();
}
-
- clearUploadProfileImagePath();
}
BOOL LLPanelProfileSecondLife::postBuild()
@@ -594,11 +623,14 @@ BOOL LLPanelProfileSecondLife::postBuild()
mSecondLifePic = getChild<LLIconCtrl>("2nd_life_pic");
mSecondLifePicLayout = getChild<LLPanel>("image_stack");
mDescriptionEdit = getChild<LLTextBase>("sl_description_edit");
- mGiveInvPanel = getChild<LLPanel>("give_stack");
mAgentActionMenuButton = getChild<LLMenuButton>("agent_actions_menu");
+ mSaveDescriptionChanges = getChild<LLButton>("save_description_changes");
+ mDiscardDescriptionChanges = getChild<LLButton>("discard_description_changes");
- mGroupList->setDoubleClickCallback(boost::bind(&LLPanelProfileSecondLife::openGroupProfile, this));
- mGroupList->setReturnCallback(boost::bind(&LLPanelProfileSecondLife::openGroupProfile, this));
+ mGroupList->setDoubleClickCallback([this](LLUICtrl*, S32 x, S32 y, MASK mask) { LLPanelProfileSecondLife::openGroupProfile(); });
+ mGroupList->setReturnCallback([this](LLUICtrl*, const LLSD&) { LLPanelProfileSecondLife::openGroupProfile(); });
+ mSaveDescriptionChanges->setCommitCallback([this](LLUICtrl*, void*) { onSaveDescriptionChanges(); }, nullptr);
+ mDiscardDescriptionChanges->setCommitCallback([this](LLUICtrl*, void*) { onDiscardDescriptionChanges(); }, nullptr);
return TRUE;
}
@@ -615,10 +647,10 @@ void LLPanelProfileSecondLife::onOpen(const LLSD& key)
BOOL own_profile = getSelfProfile();
mGroupList->setShowNone(!own_profile);
- //mGiveInvPanel->setVisible(!own_profile);
childSetVisible("notes_panel", !own_profile);
childSetVisible("settings_panel", own_profile);
+ childSetVisible("about_buttons_panel", own_profile);
childSetVisible("permissions_panel", !own_profile);
if (own_profile && !getEmbedded())
@@ -638,12 +670,11 @@ void LLPanelProfileSecondLife::onOpen(const LLSD& key)
if (own_profile)
{
- //mAgentActionMenuButton->setMenu("menu_profile_self.xml", LLMenuButton::MP_BOTTOM_RIGHT);
+ mAgentActionMenuButton->setMenu("menu_profile_self.xml", LLMenuButton::MP_BOTTOM_RIGHT);
}
else
{
// Todo: use PeopleContextMenu instead?
- // Todo: add options to copy name, display name, id, may be slurl
mAgentActionMenuButton->setMenu("menu_profile_other.xml", LLMenuButton::MP_BOTTOM_RIGHT);
}
@@ -665,6 +696,7 @@ void LLPanelProfileSecondLife::onOpen(const LLSD& key)
mAvatarNameCacheConnection = LLAvatarNameCache::get(getAvatarId(), boost::bind(&LLPanelProfileSecondLife::onAvatarNameCache, this, _1, _2));
}
+// todo:: remove apply
void LLPanelProfileSecondLife::apply(LLAvatarData* data)
{
if (getIsLoaded() && getSelfProfile())
@@ -675,7 +707,6 @@ void LLPanelProfileSecondLife::apply(LLAvatarData* data)
LLSD params = LLSDMap();
// we have an image, check if it is local. Server won't recognize local ids.
if (data->image_id != mImageAssetId
- && mImageFile.empty()
&& !LLLocalBitmapMgr::getInstance()->isLocal(mImageAssetId))
{
params["sl_image_id"] = mImageAssetId;
@@ -701,22 +732,6 @@ void LLPanelProfileSecondLife::apply(LLAvatarData* data)
LL_WARNS("AvatarProperties") << "Failed to update profile data, no cap found" << LL_ENDL;
}
}
-
- // Only if image is local
- if (!mImageFile.empty())
- {
- std::string cap_url = gAgent.getRegionCapability(PROFILE_IMAGE_UPLOAD_CAP);
- if (!cap_url.empty())
- {
- LLCoros::instance().launch("postAgentUserImageCoro",
- boost::bind(post_profile_image_coro, cap_url, PROFILE_IMAGE_SL, mImageFile));
- mImageFile.clear(); // coro should do the deleting
- }
- else
- {
- LL_WARNS("AvatarProperties") << "Failed to upload profile image of type " << (S32)PROFILE_IMAGE_SL << ", no cap found" << LL_ENDL;
- }
- }
}
}
@@ -769,8 +784,6 @@ void LLPanelProfileSecondLife::resetData()
mDescriptionEdit->setValue(LLStringUtil::null);
mGroups.clear();
mGroupList->setGroups(mGroups);
- clearUploadProfileImagePath();
- //mAgentActionMenuButton set menu
}
void LLPanelProfileSecondLife::processProfileProperties(const LLAvatarData* avatar_data)
@@ -834,35 +847,34 @@ void LLPanelProfileSecondLife::onAvatarNameCache(const LLUUID& agent_id, const L
getChild<LLUICtrl>("user_name")->setValue(av_name.getUserName() );
}
-void LLPanelProfileSecondLife::setUploadProfileImagePath(const std::string &path, const std::string &orig_path)
+void LLPanelProfileSecondLife::setProfileImageUploading(bool loading)
{
- clearUploadProfileImagePath();
- // todo: display this in floater,
- // LLIconCtrl can't show a path, only by id or name, so may be draw directly or add as a local bitmap?
- // LLLocalBitmap* unit = new LLLocalBitmap(path);
-
- // assign a local texture to view in viewer
- // Todo: remove LLLocalBitmap and just draw texture instead
- // orig_path was used instead of path, since LLLocalBitmapMgr does not support j2c
- LLUUID tracking_id = LLLocalBitmapMgr::getInstance()->addUnit(orig_path);
- if (tracking_id.isNull())
- {
- // todo: error handling
- return;
- }
-
- mImageFile = path;
- mImageAssetId = LLLocalBitmapMgr::getInstance()->getWorldID(tracking_id);
- mSecondLifePic->setValue(mImageAssetId);
+ // Todo: loading indicator here
+ mWaitingForImageUpload = loading;
}
-void LLPanelProfileSecondLife::clearUploadProfileImagePath()
+void LLPanelProfileSecondLife::setProfileImageUploaded(const LLUUID &image_asset_id)
{
- if (!mImageFile.empty())
+ mSecondLifePic->setValue(image_asset_id);
+
+ LLViewerFetchedTexture* imagep = LLViewerTextureManager::getFetchedTexture(image_asset_id);
+ if (imagep->getFullHeight())
+ {
+ onImageLoaded(true, imagep);
+ }
+ else
{
- LLFile::remove(mImageFile); //todo: supress errors, may be not need to remove if it becomes a LLLocalBitmap
+ imagep->setLoadedCallback(onImageLoaded,
+ MAX_DISCARD_LEVEL,
+ FALSE,
+ FALSE,
+ new LLHandle<LLPanel>(getHandle()),
+ NULL,
+ FALSE);
}
- mImageFile.clear();
+
+ mWaitingForImageUpload = false;
+ // Todo: reset loading indicator here
}
void LLPanelProfileSecondLife::fillCommonData(const LLAvatarData* avatar_data)
@@ -879,7 +891,7 @@ void LLPanelProfileSecondLife::fillCommonData(const LLAvatarData* avatar_data)
mImageAssetId = avatar_data->image_id;
mSecondLifePic->setValue(mImageAssetId);
- //Don't bother about boost level, picker will set it
+ // Will be loaded as a LLViewerFetchedTexture::BOOST_UI due to mSecondLifePic
LLViewerFetchedTexture* imagep = LLViewerTextureManager::getFetchedTexture(avatar_data->image_id);
if (imagep->getFullHeight())
{
@@ -1046,14 +1058,11 @@ void LLPanelProfileSecondLife::updateButtons()
mShowInSearchCheckbox->setVisible(TRUE);
mShowInSearchCheckbox->setEnabled(TRUE);
mDescriptionEdit->setEnabled(TRUE);
- }
-}
-void LLPanelProfileSecondLife::onClickSetName()
-{
- LLAvatarNameCache::get(getAvatarId(), boost::bind(&LLPanelProfileSecondLife::onAvatarNameCacheSetName, this, _1, _2));
-
- LLFirstUse::setDisplayName(false);
+ // todo: enable/disble buttons based on text changes
+ //mSaveDescriptionChanges->
+ //mDiscardDescriptionChanges->
+ }
}
@@ -1061,17 +1070,19 @@ void LLPanelProfileSecondLife::onClickSetName()
class LLProfileImagePicker : public LLFilePickerThread
{
public:
- LLProfileImagePicker(LLHandle<LLPanel> *handle);
+ LLProfileImagePicker(EProfileImageType type, LLHandle<LLPanel> *handle);
~LLProfileImagePicker();
virtual void notify(const std::vector<std::string>& filenames);
private:
LLHandle<LLPanel> *mHandle;
+ EProfileImageType mType;
};
-LLProfileImagePicker::LLProfileImagePicker(LLHandle<LLPanel> *handle)
+LLProfileImagePicker::LLProfileImagePicker(EProfileImageType type, LLHandle<LLPanel> *handle)
: LLFilePickerThread(LLFilePicker::FFLOAD_IMAGE),
- mHandle(handle)
+ mHandle(handle),
+ mType(type)
{
}
@@ -1082,10 +1093,6 @@ LLProfileImagePicker::~LLProfileImagePicker()
void LLProfileImagePicker::notify(const std::vector<std::string>& filenames)
{
- /*if (LLAppViewer::instance()->quitRequested())
- {
- return;
- }*/
if (mHandle->isDead())
{
return;
@@ -1102,17 +1109,25 @@ void LLProfileImagePicker::notify(const std::vector<std::string>& filenames)
const S32 MAX_DIM = 256;
if (!LLViewerTextureList::createUploadFile(file_path, temp_file, codec, MAX_DIM))
{
- // todo: error handling
+ //todo: image not supported notification
+ LL_WARNS("AvatarProperties") << "Failed to upload profile image of type " << (S32)PROFILE_IMAGE_SL << ", failed to open image" << LL_ENDL;
+ return;
+ }
+
+ std::string cap_url = gAgent.getRegionCapability(PROFILE_IMAGE_UPLOAD_CAP);
+ if (cap_url.empty())
+ {
+ LL_WARNS("AvatarProperties") << "Failed to upload profile image of type " << (S32)PROFILE_IMAGE_SL << ", no cap found" << LL_ENDL;
return;
}
LLPanelProfileSecondLife* panel = static_cast<LLPanelProfileSecondLife*>(mHandle->get());
- panel->setUploadProfileImagePath(temp_file, file_path);
-}
+ panel->setProfileImageUploading(true);
-void LLPanelProfileSecondLife::onPickTexture()
-{
- (new LLProfileImagePicker(new LLHandle<LLPanel>(getHandle())))->getFile();
+ LLCoros::instance().launch("postAgentUserImageCoro",
+ boost::bind(post_profile_image_coro, cap_url, mType, temp_file, mHandle));
+
+ mHandle = nullptr; // transferred to post_profile_image_coro
}
void LLPanelProfileSecondLife::onCommitMenu(const LLSD& userdata)
@@ -1169,6 +1184,63 @@ void LLPanelProfileSecondLife::onCommitMenu(const LLSD& userdata)
{
LLAvatarActions::toggleBlock(agent_id);
}
+ else if (item_name == "copy_user_id")
+ {
+ LLWString wstr = utf8str_to_wstring(getAvatarId().asString());
+ LLClipboard::instance().copyToClipboard(wstr, 0, wstr.size());
+ }
+ else if (item_name == "copy_display_name"
+ || item_name == "copy_username")
+ {
+ LLAvatarName av_name;
+ if (!LLAvatarNameCache::get(getAvatarId(), &av_name))
+ {
+ // shouldn't happen, option is supposed to be invisible while name is fetching
+ LL_WARNS() << "Failed to get agent data" << LL_ENDL;
+ return;
+ }
+ LLWString wstr;
+ if (item_name == "copy_display_name")
+ {
+ wstr = utf8str_to_wstring(av_name.getDisplayName(true));
+ }
+ else if (item_name == "copy_username")
+ {
+ wstr = utf8str_to_wstring(av_name.getUserName());
+ }
+ LLClipboard::instance().copyToClipboard(wstr, 0, wstr.size());
+ }
+ else if (item_name == "edit_display_name")
+ {
+ LLAvatarNameCache::get(getAvatarId(), boost::bind(&LLPanelProfileSecondLife::onAvatarNameCacheSetName, this, _1, _2));
+ LLFirstUse::setDisplayName(false);
+ }
+ else if (item_name == "edit_partner")
+ {
+ // todo: open https://secondlife.com/my/account/partners.php or whatever link is correct for the grid
+ }
+ else if (item_name == "change_photo")
+ {
+ (new LLProfileImagePicker(PROFILE_IMAGE_SL, new LLHandle<LLPanel>(getHandle())))->getFile();
+ }
+ else if (item_name == "remove_photo")
+ {
+ LLSD params;
+ params["sl_image_id"] = LLUUID::null; // todo: verify that it works and matches Generic_Person_Large
+
+ std::string cap_url = gAgent.getRegionCapability(PROFILE_PROPERTIES_CAP);
+ if (!cap_url.empty())
+ {
+ LLCoros::instance().launch("putAgentUserInfoCoro",
+ boost::bind(put_avatar_properties_coro, cap_url, getAvatarId(), params));
+
+ mSecondLifePic->setValue("Generic_Person_Large");
+ }
+ else
+ {
+ LL_WARNS("AvatarProperties") << "Failed to update profile data, no cap found" << LL_ENDL;
+ }
+ }
}
bool LLPanelProfileSecondLife::onEnableMenu(const LLSD& userdata)
@@ -1181,7 +1253,7 @@ bool LLPanelProfileSecondLife::onEnableMenu(const LLSD& userdata)
}
else if (item_name == "voice_call")
{
- return LLAvatarActions::canCall();
+ return mVoiceStatus;
}
else if (item_name == "callog")
{
@@ -1204,6 +1276,21 @@ bool LLPanelProfileSecondLife::onEnableMenu(const LLSD& userdata)
{
return LLAvatarActions::canBlock(agent_id);
}
+ else if (item_name == "copy_display_name"
+ || item_name == "copy_username")
+ {
+ return !mAvatarNameCacheConnection.connected();
+ }
+ else if (item_name == "change_photo")
+ {
+ std::string cap_url = gAgent.getRegionCapability(PROFILE_IMAGE_UPLOAD_CAP);
+ return !cap_url.empty() && !mWaitingForImageUpload;
+ }
+ else if (item_name == "remove_photo")
+ {
+ std::string cap_url = gAgent.getRegionCapability(PROFILE_PROPERTIES_CAP);
+ return !cap_url.empty() && !mWaitingForImageUpload;
+ }
return false;
}
@@ -1247,6 +1334,35 @@ void LLPanelProfileSecondLife::onAvatarNameCacheSetName(const LLUUID& agent_id,
LLFloaterReg::showInstance("display_name");
}
+void LLPanelProfileSecondLife::onSaveDescriptionChanges()
+{
+ // todo: force commit changes in mDescriptionEdit, reset dirty flags
+ // todo: check if mDescriptionEdit can be made to not commit immediately
+
+ LLSD params;
+ params["sl_about_text"] = mDescriptionEdit->getValue().asString();
+
+ std::string cap_url = gAgent.getRegionCapability(PROFILE_PROPERTIES_CAP);
+ if (!cap_url.empty())
+ {
+ LLCoros::instance().launch("putAgentUserInfoCoro",
+ boost::bind(put_avatar_properties_coro, cap_url, getAvatarId(), params));
+ }
+ else
+ {
+ LL_WARNS("AvatarProperties") << "Failed to update profile data, no cap found" << LL_ENDL;
+ }
+
+ updateButtons();
+}
+
+void LLPanelProfileSecondLife::onDiscardDescriptionChanges()
+{
+ // todo: restore mDescriptionEdit
+
+ updateButtons();
+}
+
//////////////////////////////////////////////////////////////////////////
// LLPanelProfileWeb
@@ -1514,7 +1630,7 @@ void LLPanelProfileFirstLife::apply(LLAvatarData* data)
{
// todo: temporary file, connect to UI
std::string file_path = gDirUtilp->findSkinnedFilename("textures", "icons/Default_Outfit_Photo.png");
- launch_profile_image_coro(PROFILE_IMAGE_FL, file_path);
+ launch_profile_image_coro(PROFILE_IMAGE_FL, file_path, new LLHandle<LLPanel>(getHandle()));
}
}
diff --git a/indra/newview/llpanelprofile.h b/indra/newview/llpanelprofile.h
index f695167a89..fb38a361cb 100644
--- a/indra/newview/llpanelprofile.h
+++ b/indra/newview/llpanelprofile.h
@@ -45,6 +45,7 @@
// class LLPanelProfileNotes;
class LLAvatarName;
+class LLButton;
class LLCheckBoxCtrl;
class LLIconCtrl;
class LLTabContainer;
@@ -103,8 +104,8 @@ public:
void onAvatarNameCache(const LLUUID& agent_id, const LLAvatarName& av_name);
- void setUploadProfileImagePath(const std::string &path, const std::string &orig_path);
- void clearUploadProfileImagePath();
+ void setProfileImageUploading(bool loading);
+ void setProfileImageUploaded(const LLUUID &image_asset_id);
friend void request_avatar_properties_coro(std::string cap_url, LLUUID agent_id);
@@ -162,13 +163,14 @@ protected:
private:
/*virtual*/ void updateButtons();
- void onClickSetName();
- void onPickTexture();
void onCommitMenu(const LLSD& userdata);
bool onEnableMenu(const LLSD& userdata);
bool onCheckMenu(const LLSD& userdata);
void onAvatarNameCacheSetName(const LLUUID& id, const LLAvatarName& av_name);
+ void onSaveDescriptionChanges();
+ void onDiscardDescriptionChanges();
+
private:
typedef std::map<std::string, LLUUID> group_map_t;
group_map_t mGroups;
@@ -179,11 +181,12 @@ private:
LLIconCtrl* mSecondLifePic;
LLPanel* mSecondLifePicLayout;
LLTextBase* mDescriptionEdit;
- LLPanel* mGiveInvPanel;
LLMenuButton* mAgentActionMenuButton;
+ LLButton* mSaveDescriptionChanges;
+ LLButton* mDiscardDescriptionChanges;
bool mVoiceStatus;
- std::string mImageFile;
+ bool mWaitingForImageUpload;
LLUUID mImageAssetId;
boost::signals2::connection mAvatarNameCacheConnection;
diff --git a/indra/newview/llviewertexturelist.cpp b/indra/newview/llviewertexturelist.cpp
index 7afc310fdd..b97f3874b7 100644
--- a/indra/newview/llviewertexturelist.cpp
+++ b/indra/newview/llviewertexturelist.cpp
@@ -1264,7 +1264,6 @@ BOOL LLViewerTextureList::createUploadFile(const std::string& filename,
LLPointer<LLImageFormatted> image = LLImageFormatted::createFromType(codec);
if (image.isNull())
{
- image->setLastError("Couldn't open the image to be uploaded.");
return FALSE;
}
if (!image->load(filename))
diff --git a/indra/newview/skins/default/xui/en/menu_profile_other.xml b/indra/newview/skins/default/xui/en/menu_profile_other.xml
index 5fc625b8e5..7731ee65d1 100644
--- a/indra/newview/skins/default/xui/en/menu_profile_other.xml
+++ b/indra/newview/skins/default/xui/en/menu_profile_other.xml
@@ -126,4 +126,35 @@
function="Profile.EnableItem"
parameter="toggle_block_agent"/>
</menu_item_check>
+ <menu_item_separator name="separator_copy_options"/>
+ <menu_item_call
+ label="Copy Display Name"
+ layout="topleft"
+ name="copy_display_name">
+ <menu_item_call.on_click
+ function="Profile.Commit"
+ parameter="copy_display_name"/>
+ <menu_item_call.on_enable
+ function="Profile.EnableItem"
+ parameter="copy_display_name"/>
+ </menu_item_call>
+ <menu_item_call
+ label="Copy Agent Name"
+ layout="topleft"
+ name="copy_name">
+ <menu_item_call.on_click
+ function="Profile.Commit"
+ parameter="copy_username"/>
+ <menu_item_call.on_enable
+ function="Profile.EnableItem"
+ parameter="copy_username"/>
+ </menu_item_call>
+ <menu_item_call
+ label="Copy Agent Id"
+ layout="topleft"
+ name="copy_id">
+ <menu_item_call.on_click
+ function="Profile.Commit"
+ parameter="copy_user_id"/>
+ </menu_item_call>
</toggleable_menu>
diff --git a/indra/newview/skins/default/xui/en/menu_profile_self.xml b/indra/newview/skins/default/xui/en/menu_profile_self.xml
new file mode 100644
index 0000000000..552c96c60c
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/menu_profile_self.xml
@@ -0,0 +1,74 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<toggleable_menu
+ layout="topleft"
+ name="Avatar Profile Menu Self">
+ <menu_item_call
+ label="Edit Display Name"
+ layout="topleft"
+ name="edit_display_name">
+ <on_click
+ function="Profile.Commit"
+ parameter="edit_display_name"/>
+ </menu_item_call>
+ <menu_item_call
+ label="Edit Partner"
+ layout="topleft"
+ name="edit_partner">
+ <on_click
+ function="Profile.Commit"
+ parameter="edit_partner"/>
+ </menu_item_call>
+ <menu_item_call
+ label="Change Photo"
+ layout="topleft"
+ name="change_photo">
+ <menu_item_call.on_click
+ function="Profile.Commit"
+ parameter="change_photo"/>
+ <menu_item_call.on_enable
+ function="Profile.EnableItem"
+ parameter="change_photo"/>
+ </menu_item_call>
+ <menu_item_call
+ label="Remove Photo"
+ layout="topleft"
+ name="remove_photo">
+ <menu_item_call.on_click
+ function="Profile.Commit"
+ parameter="remove_photo"/>
+ <menu_item_call.on_enable
+ function="Profile.EnableItem"
+ parameter="remove_photo"/>
+ </menu_item_call>
+ <menu_item_separator name="separator_copy_options"/>
+ <menu_item_call
+ label="Copy Display Name"
+ layout="topleft"
+ name="copy_display_name">
+ <menu_item_call.on_click
+ function="Profile.Commit"
+ parameter="copy_display_name"/>
+ <menu_item_call.on_enable
+ function="Profile.EnableItem"
+ parameter="copy_display_name"/>
+ </menu_item_call>
+ <menu_item_call
+ label="Copy Agent Name"
+ layout="topleft"
+ name="copy_name">
+ <menu_item_call.on_click
+ function="Profile.Commit"
+ parameter="copy_username"/>
+ <menu_item_call.on_enable
+ function="Profile.EnableItem"
+ parameter="copy_username"/>
+ </menu_item_call>
+ <menu_item_call
+ label="Copy Agent Id"
+ layout="topleft"
+ name="copy_id">
+ <menu_item_call.on_click
+ function="Profile.Commit"
+ parameter="copy_user_id"/>
+ </menu_item_call>
+</toggleable_menu>
diff --git a/indra/newview/skins/default/xui/en/panel_profile_secondlife.xml b/indra/newview/skins/default/xui/en/panel_profile_secondlife.xml
index 4b40db9b5d..3ed704b090 100644
--- a/indra/newview/skins/default/xui/en/panel_profile_secondlife.xml
+++ b/indra/newview/skins/default/xui/en/panel_profile_secondlife.xml
@@ -264,10 +264,10 @@ Account: [ACCTTYPE]
<layout_stack
name="groups_notes_settings_stack"
- top="1"
+ top="0"
left="1"
right="-1"
- bottom="-1"
+ height="159"
follows="all"
layout="topleft"
orientation="horizontal">