From 4ca8d3417ca0d98f723cbf708cb37ca4f0eeec93 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Wed, 6 Dec 2023 01:01:06 +0200 Subject: SL-18107 Allow dropping inventory onto a profile for sharing --- indra/newview/llpanelprofile.cpp | 46 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) (limited to 'indra/newview/llpanelprofile.cpp') diff --git a/indra/newview/llpanelprofile.cpp b/indra/newview/llpanelprofile.cpp index c2c9139c19..24091644e3 100644 --- a/indra/newview/llpanelprofile.cpp +++ b/indra/newview/llpanelprofile.cpp @@ -46,6 +46,7 @@ #include "lltexteditor.h" #include "lltexturectrl.h" #include "lltoggleablemenu.h" +#include "lltooldraganddrop.h" #include "llgrouplist.h" #include "llurlaction.h" @@ -998,6 +999,51 @@ void LLPanelProfileSecondLife::onOpen(const LLSD& key) mAvatarNameCacheConnection = LLAvatarNameCache::get(getAvatarId(), boost::bind(&LLPanelProfileSecondLife::onAvatarNameCache, this, _1, _2)); } + +BOOL LLPanelProfileSecondLife::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, + EDragAndDropType cargo_type, + void* cargo_data, + EAcceptance* accept, + std::string& tooltip_msg) +{ + // Try children first + if (LLPanelProfileTab::handleDragAndDrop(x, y, mask, drop, cargo_type, cargo_data, accept, tooltip_msg) + && *accept != ACCEPT_NO) + { + return TRUE; + } + + // No point sharing with own profile + if (getSelfProfile()) + { + return FALSE; + } + + // Exclude fields that look like they are editable. + S32 child_x = 0; + S32 child_y = 0; + if (localPointToOtherView(x, y, &child_x, &child_y, mDescriptionEdit) + && mDescriptionEdit->pointInView(child_x, child_y)) + { + return FALSE; + } + + if (localPointToOtherView(x, y, &child_x, &child_y, mGroupList) + && mGroupList->pointInView(child_x, child_y)) + { + return FALSE; + } + + // Share + LLToolDragAndDrop::handleGiveDragAndDrop(getAvatarId(), + LLUUID::null, + drop, + cargo_type, + cargo_data, + accept); + return TRUE; +} + void LLPanelProfileSecondLife::updateData() { LLUUID avatar_id = getAvatarId(); -- cgit v1.2.3 From a5261a5fa8fad810ecb5c260d92c3e771822bf58 Mon Sep 17 00:00:00 2001 From: Ansariel Date: Tue, 20 Feb 2024 23:46:23 +0100 Subject: Convert BOOL to bool in llui --- indra/newview/llpanelprofile.cpp | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) (limited to 'indra/newview/llpanelprofile.cpp') diff --git a/indra/newview/llpanelprofile.cpp b/indra/newview/llpanelprofile.cpp index 00fa3853f7..be5783dd50 100644 --- a/indra/newview/llpanelprofile.cpp +++ b/indra/newview/llpanelprofile.cpp @@ -534,7 +534,7 @@ public: { if (params.size() < 2) return false; LLUUID avatar_id; - if (!avatar_id.set(params[0], FALSE)) + if (!avatar_id.set(params[0], false)) { return false; } @@ -661,7 +661,7 @@ class LLFloaterProfilePermissions public: LLFloaterProfilePermissions(LLView * owner, const LLUUID &avatar_id); ~LLFloaterProfilePermissions(); - BOOL postBuild() override; + bool postBuild() override; void onOpen(const LLSD& key) override; void draw() override; void changed(U32 mask) override; // LLFriendObserver @@ -713,7 +713,7 @@ LLFloaterProfilePermissions::~LLFloaterProfilePermissions() } } -BOOL LLFloaterProfilePermissions::postBuild() +bool LLFloaterProfilePermissions::postBuild() { mDescription = getChild("perm_description"); mOnlineStatus = getChild("online_check"); @@ -728,7 +728,7 @@ BOOL LLFloaterProfilePermissions::postBuild() mOkBtn->setCommitCallback([this](LLUICtrl*, void*) { onApplyRights(); }, nullptr); mCancelBtn->setCommitCallback([this](LLUICtrl*, void*) { onCancel(); }, nullptr); - return TRUE; + return true; } void LLFloaterProfilePermissions::onOpen(const LLSD& key) @@ -925,7 +925,7 @@ LLPanelProfileSecondLife::~LLPanelProfileSecondLife() } } -BOOL LLPanelProfileSecondLife::postBuild() +bool LLPanelProfileSecondLife::postBuild() { mGroupList = getChild("group_list"); mShowInSearchCombo = getChild("show_in_search"); @@ -957,7 +957,7 @@ BOOL LLPanelProfileSecondLife::postBuild() mCantEditObjectsIcon->setMouseUpCallback([this](LLUICtrl*, S32 x, S32 y, MASK mask) { onShowAgentPermissionsDialog(); }); mSecondLifePic->setMouseUpCallback([this](LLUICtrl*, S32 x, S32 y, MASK mask) { onShowAgentProfileTexture(); }); - return TRUE; + return true; } void LLPanelProfileSecondLife::onOpen(const LLSD& key) @@ -1014,7 +1014,7 @@ void LLPanelProfileSecondLife::onOpen(const LLSD& key) } -BOOL LLPanelProfileSecondLife::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, +bool LLPanelProfileSecondLife::handleDragAndDrop(S32 x, S32 y, MASK mask, bool drop, EDragAndDropType cargo_type, void* cargo_data, EAcceptance* accept, @@ -1024,13 +1024,13 @@ BOOL LLPanelProfileSecondLife::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL d if (LLPanelProfileTab::handleDragAndDrop(x, y, mask, drop, cargo_type, cargo_data, accept, tooltip_msg) && *accept != ACCEPT_NO) { - return TRUE; + return true; } // No point sharing with own profile if (getSelfProfile()) { - return FALSE; + return false; } // Exclude fields that look like they are editable. @@ -2124,13 +2124,13 @@ void LLPanelProfileWeb::onOpen(const LLSD& key) mAvatarNameCacheConnection = LLAvatarNameCache::get(getAvatarId(), boost::bind(&LLPanelProfileWeb::onAvatarNameCache, this, _1, _2)); } -BOOL LLPanelProfileWeb::postBuild() +bool LLPanelProfileWeb::postBuild() { mWebBrowser = getChild("profile_html"); mWebBrowser->addObserver(this); mWebBrowser->setHomePageUrl("about:blank"); - return TRUE; + return true; } void LLPanelProfileWeb::resetData() @@ -2249,7 +2249,7 @@ LLPanelProfileFirstLife::~LLPanelProfileFirstLife() { } -BOOL LLPanelProfileFirstLife::postBuild() +bool LLPanelProfileFirstLife::postBuild() { mDescriptionEdit = getChild("fl_description_edit"); mPicture = getChild("real_world_pic"); @@ -2267,7 +2267,7 @@ BOOL LLPanelProfileFirstLife::postBuild() mDiscardChanges->setCommitCallback([this](LLUICtrl*, void*) { onDiscardDescriptionChanges(); }, nullptr); mDescriptionEdit->setKeystrokeCallback([this](LLTextEditor* caller) { onSetDescriptionDirty(); }); - return TRUE; + return true; } void LLPanelProfileFirstLife::onOpen(const LLSD& key) @@ -2544,7 +2544,7 @@ void LLPanelProfileNotes::commitUnsavedChanges() } } -BOOL LLPanelProfileNotes::postBuild() +bool LLPanelProfileNotes::postBuild() { mNotesEditor = getChild("notes_edit"); mSaveChanges = getChild("notes_save_changes"); @@ -2554,7 +2554,7 @@ BOOL LLPanelProfileNotes::postBuild() mDiscardChanges->setCommitCallback([this](LLUICtrl*, void*) { onDiscardNotesChanges(); }, nullptr); mNotesEditor->setKeystrokeCallback([this](LLTextEditor* caller) { onSetNotesDirty(); }); - return TRUE; + return true; } void LLPanelProfileNotes::onOpen(const LLSD& key) @@ -2639,9 +2639,9 @@ LLPanelProfile::~LLPanelProfile() { } -BOOL LLPanelProfile::postBuild() +bool LLPanelProfile::postBuild() { - return TRUE; + return true; } void LLPanelProfile::onTabChange() -- cgit v1.2.3 From 60d3dd98a44230c21803c1606552ee098ed9fa7c Mon Sep 17 00:00:00 2001 From: Ansariel Date: Wed, 21 Feb 2024 21:05:14 +0100 Subject: Convert remaining BOOL to bool --- indra/newview/llpanelprofile.cpp | 188 +++++++++++++++++++-------------------- 1 file changed, 94 insertions(+), 94 deletions(-) (limited to 'indra/newview/llpanelprofile.cpp') diff --git a/indra/newview/llpanelprofile.cpp b/indra/newview/llpanelprofile.cpp index be5783dd50..92a8a826ac 100644 --- a/indra/newview/llpanelprofile.cpp +++ b/indra/newview/llpanelprofile.cpp @@ -138,7 +138,7 @@ void request_avatar_properties_coro(std::string cap_url, LLUUID agent_id) return; } - LLPanel *panel = floater_profile->findChild(PANEL_PROFILE_VIEW, TRUE); + LLPanel *panel = floater_profile->findChild(PANEL_PROFILE_VIEW, true); LLPanelProfile *panel_profile = dynamic_cast(panel); if (!panel_profile) { @@ -192,21 +192,21 @@ void request_avatar_properties_coro(std::string cap_url, LLUUID agent_id) avatar_data->caption_text = result["caption"].asString(); } - panel = floater_profile->findChild(PANEL_SECONDLIFE, TRUE); + panel = floater_profile->findChild(PANEL_SECONDLIFE, true); LLPanelProfileSecondLife *panel_sl = dynamic_cast(panel); if (panel_sl) { panel_sl->processProfileProperties(avatar_data); } - panel = floater_profile->findChild(PANEL_WEB, TRUE); + panel = floater_profile->findChild(PANEL_WEB, true); LLPanelProfileWeb *panel_web = dynamic_cast(panel); if (panel_web) { panel_web->setLoaded(); } - panel = floater_profile->findChild(PANEL_FIRSTLIFE, TRUE); + panel = floater_profile->findChild(PANEL_FIRSTLIFE, true); LLPanelProfileFirstLife *panel_first = dynamic_cast(panel); if (panel_first) { @@ -226,7 +226,7 @@ void request_avatar_properties_coro(std::string cap_url, LLUUID agent_id) avatar_picks.picks_list.emplace_back(pick_data["id"].asUUID(), pick_data["name"].asString()); } - panel = floater_profile->findChild(PANEL_PICKS, TRUE); + panel = floater_profile->findChild(PANEL_PICKS, true); LLPanelProfilePicks *panel_picks = dynamic_cast(panel); if (panel_picks) { @@ -267,7 +267,7 @@ void request_avatar_properties_coro(std::string cap_url, LLUUID agent_id) avatar_notes.target_id = agent_id; avatar_notes.notes = result["notes"].asString(); - panel = floater_profile->findChild(PANEL_NOTES, TRUE); + panel = floater_profile->findChild(PANEL_NOTES, true); LLPanelProfileNotes *panel_notes = dynamic_cast(panel); if (panel_notes) { @@ -779,11 +779,11 @@ void LLFloaterProfilePermissions::fillRightsData() { S32 rights = relation->getRightsGrantedTo(); - BOOL see_online = LLRelationship::GRANT_ONLINE_STATUS & rights ? TRUE : FALSE; + bool see_online = LLRelationship::GRANT_ONLINE_STATUS & rights ? true : false; mOnlineStatus->setValue(see_online); mMapRights->setEnabled(see_online); - mMapRights->setValue(LLRelationship::GRANT_MAP_LOCATION & rights ? TRUE : FALSE); - mEditObjectRights->setValue(LLRelationship::GRANT_MODIFY_OBJECTS & rights ? TRUE : FALSE); + mMapRights->setValue(LLRelationship::GRANT_MAP_LOCATION & rights ? true : false); + mEditObjectRights->setValue(LLRelationship::GRANT_MODIFY_OBJECTS & rights ? true : false); } else { @@ -798,7 +798,7 @@ void LLFloaterProfilePermissions::rightsConfirmationCallback(const LLSD& notific S32 option = LLNotificationsUtil::getSelectedOption(notification, response); if (option != 0) // canceled { - mEditObjectRights->setValue(mEditObjectRights->getValue().asBoolean() ? FALSE : TRUE); + mEditObjectRights->setValue(mEditObjectRights->getValue().asBoolean() ? false : true); } else { @@ -824,7 +824,7 @@ void LLFloaterProfilePermissions::onCommitSeeOnlineRights() if (relation) { S32 rights = relation->getRightsGrantedTo(); - mMapRights->setValue(LLRelationship::GRANT_MAP_LOCATION & rights ? TRUE : FALSE); + mMapRights->setValue(LLRelationship::GRANT_MAP_LOCATION & rights ? true : false); } else { @@ -834,7 +834,7 @@ void LLFloaterProfilePermissions::onCommitSeeOnlineRights() } else { - mMapRights->setValue(FALSE); + mMapRights->setValue(false); } mHasUnsavedPermChanges = true; } @@ -968,7 +968,7 @@ void LLPanelProfileSecondLife::onOpen(const LLSD& key) LLUUID avatar_id = getAvatarId(); - BOOL own_profile = getSelfProfile(); + bool own_profile = getSelfProfile(); mGroupList->setShowNone(!own_profile); @@ -1005,7 +1005,7 @@ void LLPanelProfileSecondLife::onOpen(const LLSD& key) if (!own_profile) { - mVoiceStatus = LLAvatarActions::canCall() && (LLAvatarActions::isFriend(avatar_id) ? LLAvatarTracker::instance().isBuddyOnline(avatar_id) : TRUE); + mVoiceStatus = LLAvatarActions::canCall() && (LLAvatarActions::isFriend(avatar_id) ? LLAvatarTracker::instance().isBuddyOnline(avatar_id) : true); updateOnlineStatus(); fillRightsData(); } @@ -1039,13 +1039,13 @@ bool LLPanelProfileSecondLife::handleDragAndDrop(S32 x, S32 y, MASK mask, bool d if (localPointToOtherView(x, y, &child_x, &child_y, mDescriptionEdit) && mDescriptionEdit->pointInView(child_x, child_y)) { - return FALSE; + return false; } if (localPointToOtherView(x, y, &child_x, &child_y, mGroupList) && mGroupList->pointInView(child_x, child_y)) { - return FALSE; + return false; } // Share @@ -1055,7 +1055,7 @@ bool LLPanelProfileSecondLife::handleDragAndDrop(S32 x, S32 y, MASK mask, bool d cargo_type, cargo_data, accept); - return TRUE; + return true; } void LLPanelProfileSecondLife::updateData() @@ -1116,9 +1116,9 @@ void LLPanelProfileSecondLife::resetData() mCanEditObjectsIcon->setEnabled(false); mCantEditObjectsIcon->setEnabled(false); - childSetVisible("partner_layout", FALSE); - childSetVisible("badge_layout", FALSE); - childSetVisible("partner_spacer_layout", TRUE); + childSetVisible("partner_layout", false); + childSetVisible("badge_layout", false); + childSetVisible("partner_spacer_layout", true); } void LLPanelProfileSecondLife::processProfileProperties(const LLAvatarData* avatar_data) @@ -1200,11 +1200,11 @@ void LLPanelProfileSecondLife::setProfileImageUploaded(const LLUUID &image_asset { imagep->setLoadedCallback(onImageLoaded, MAX_DISCARD_LEVEL, - FALSE, - FALSE, + false, + false, new LLHandle(getHandle()), NULL, - FALSE); + false); } LLFloater *floater = mFloaterProfileTextureHandle.get(); @@ -1287,17 +1287,17 @@ void LLPanelProfileSecondLife::fillCommonData(const LLAvatarData* avatar_data) { imagep->setLoadedCallback(onImageLoaded, MAX_DISCARD_LEVEL, - FALSE, - FALSE, + false, + false, new LLHandle(getHandle()), NULL, - FALSE); + false); } if (getSelfProfile()) { mAllowPublish = avatar_data->flags & AVATAR_ALLOW_PUBLISH; - mShowInSearchCombo->setValue((BOOL)mAllowPublish); + mShowInSearchCombo->setValue((bool)mAllowPublish); } } @@ -1306,7 +1306,7 @@ void LLPanelProfileSecondLife::fillPartnerData(const LLAvatarData* avatar_data) LLTextBox* partner_text_ctrl = getChild("partner_link"); if (avatar_data->partner_id.notNull()) { - childSetVisible("partner_layout", TRUE); + childSetVisible("partner_layout", true); LLStringUtil::format_map_t args; args["[LINK]"] = LLSLURL("agent", avatar_data->partner_id, "inspect").getSLURLString(); std::string partner_text = getString("partner_text", args); @@ -1314,7 +1314,7 @@ void LLPanelProfileSecondLife::fillPartnerData(const LLAvatarData* avatar_data) } else { - childSetVisible("partner_layout", FALSE); + childSetVisible("partner_layout", false); } } @@ -1336,48 +1336,48 @@ void LLPanelProfileSecondLife::fillAccountStatus(const LLAvatarData* avatar_data { getChild("badge_icon")->setValue("Profile_Badge_Linden"); getChild("badge_text")->setValue(getString("BadgeLinden")); - childSetVisible("badge_layout", TRUE); - childSetVisible("partner_spacer_layout", FALSE); + childSetVisible("badge_layout", true); + childSetVisible("partner_spacer_layout", false); } else if (avatar_data->born_on < sl_release) { getChild("badge_icon")->setValue("Profile_Badge_Beta"); getChild("badge_text")->setValue(getString("BadgeBeta")); - childSetVisible("badge_layout", TRUE); - childSetVisible("partner_spacer_layout", FALSE); + childSetVisible("badge_layout", true); + childSetVisible("partner_spacer_layout", false); } else if (customer_lower == "beta_lifetime") { getChild("badge_icon")->setValue("Profile_Badge_Beta_Lifetime"); getChild("badge_text")->setValue(getString("BadgeBetaLifetime")); - childSetVisible("badge_layout", TRUE); - childSetVisible("partner_spacer_layout", FALSE); + childSetVisible("badge_layout", true); + childSetVisible("partner_spacer_layout", false); } else if (customer_lower == "lifetime") { getChild("badge_icon")->setValue("Profile_Badge_Lifetime"); getChild("badge_text")->setValue(getString("BadgeLifetime")); - childSetVisible("badge_layout", TRUE); - childSetVisible("partner_spacer_layout", FALSE); + childSetVisible("badge_layout", true); + childSetVisible("partner_spacer_layout", false); } else if (customer_lower == "secondlifetime_premium") { getChild("badge_icon")->setValue("Profile_Badge_Premium_Lifetime"); getChild("badge_text")->setValue(getString("BadgePremiumLifetime")); - childSetVisible("badge_layout", TRUE); - childSetVisible("partner_spacer_layout", FALSE); + childSetVisible("badge_layout", true); + childSetVisible("partner_spacer_layout", false); } else if (customer_lower == "secondlifetime_premium_plus") { getChild("badge_icon")->setValue("Profile_Badge_Pplus_Lifetime"); getChild("badge_text")->setValue(getString("BadgePremiumPlusLifetime")); - childSetVisible("badge_layout", TRUE); - childSetVisible("partner_spacer_layout", FALSE); + childSetVisible("badge_layout", true); + childSetVisible("partner_spacer_layout", false); } else { - childSetVisible("badge_layout", FALSE); - childSetVisible("partner_spacer_layout", TRUE); + childSetVisible("badge_layout", false); + childSetVisible("partner_spacer_layout", true); } } @@ -1439,7 +1439,7 @@ void LLPanelProfileSecondLife::fillAgeData(const LLDate &born_on) getChild("user_age")->setValue(register_date); } -void LLPanelProfileSecondLife::onImageLoaded(BOOL success, LLViewerFetchedTexture *imagep) +void LLPanelProfileSecondLife::onImageLoaded(bool success, LLViewerFetchedTexture *imagep) { LLRect imageRect = mSecondLifePicLayout->getRect(); if (!success || imagep->getFullWidth() == imagep->getFullHeight()) @@ -1454,12 +1454,12 @@ void LLPanelProfileSecondLife::onImageLoaded(BOOL success, LLViewerFetchedTextur } //static -void LLPanelProfileSecondLife::onImageLoaded(BOOL success, +void LLPanelProfileSecondLife::onImageLoaded(bool success, LLViewerFetchedTexture *src_vi, LLImageRaw* src, LLImageRaw* aux_src, S32 discard_level, - BOOL final, + bool final, void* userdata) { if (!userdata) return; @@ -1499,7 +1499,7 @@ void LLPanelProfileSecondLife::onChange(EStatusType status, const std::string &c return; } - mVoiceStatus = LLAvatarActions::canCall() && (LLAvatarActions::isFriend(getAvatarId()) ? LLAvatarTracker::instance().isBuddyOnline(getAvatarId()) : TRUE); + mVoiceStatus = LLAvatarActions::canCall() && (LLAvatarActions::isFriend(getAvatarId()) ? LLAvatarTracker::instance().isBuddyOnline(getAvatarId()) : true); } void LLPanelProfileSecondLife::setAvatarId(const LLUUID& avatar_id) @@ -1552,8 +1552,8 @@ void LLPanelProfileSecondLife::setLoaded() if (getSelfProfile()) { - mShowInSearchCombo->setEnabled(TRUE); - mDescriptionEdit->setEnabled(TRUE); + mShowInSearchCombo->setEnabled(true); + mDescriptionEdit->setEnabled(true); } } @@ -1863,8 +1863,8 @@ void LLPanelProfileSecondLife::onAvatarNameCacheSetName(const LLUUID& agent_id, void LLPanelProfileSecondLife::setDescriptionText(const std::string &text) { - mSaveDescriptionChanges->setEnabled(FALSE); - mDiscardDescriptionChanges->setEnabled(FALSE); + mSaveDescriptionChanges->setEnabled(false); + mDiscardDescriptionChanges->setEnabled(false); mHasUnsavedDescriptionChanges = false; mDescriptionText = text; @@ -1873,8 +1873,8 @@ void LLPanelProfileSecondLife::setDescriptionText(const std::string &text) void LLPanelProfileSecondLife::onSetDescriptionDirty() { - mSaveDescriptionChanges->setEnabled(TRUE); - mDiscardDescriptionChanges->setEnabled(TRUE); + mSaveDescriptionChanges->setEnabled(true); + mDiscardDescriptionChanges->setEnabled(true); mHasUnsavedDescriptionChanges = true; } @@ -1914,8 +1914,8 @@ void LLPanelProfileSecondLife::onSaveDescriptionChanges() LL_WARNS("AvatarProperties") << "Failed to update profile data, no cap found" << LL_ENDL; } - mSaveDescriptionChanges->setEnabled(FALSE); - mDiscardDescriptionChanges->setEnabled(FALSE); + mSaveDescriptionChanges->setEnabled(false); + mDiscardDescriptionChanges->setEnabled(false); mHasUnsavedDescriptionChanges = false; } @@ -1935,15 +1935,15 @@ void LLPanelProfileSecondLife::onShowAgentPermissionsDialog() LLFloaterProfilePermissions * perms = new LLFloaterProfilePermissions(parent_floater, getAvatarId()); mFloaterPermissionsHandle = perms->getHandle(); perms->openFloater(); - perms->setVisibleAndFrontmost(TRUE); + perms->setVisibleAndFrontmost(true); parent_floater->addDependentFloater(mFloaterPermissionsHandle); } } else // already open { - floater->setMinimized(FALSE); - floater->setVisibleAndFrontmost(TRUE); + floater->setMinimized(false); + floater->setVisibleAndFrontmost(true); } } @@ -1971,7 +1971,7 @@ void LLPanelProfileSecondLife::onShowAgentProfileTexture() texture_view->resetAsset(); } texture_view->openFloater(); - texture_view->setVisibleAndFrontmost(TRUE); + texture_view->setVisibleAndFrontmost(true); parent_floater->addDependentFloater(mFloaterProfileTextureHandle); } @@ -1979,8 +1979,8 @@ void LLPanelProfileSecondLife::onShowAgentProfileTexture() else // already open { LLFloaterProfileTexture * texture_view = dynamic_cast(floater); - texture_view->setMinimized(FALSE); - texture_view->setVisibleAndFrontmost(TRUE); + texture_view->setMinimized(false); + texture_view->setVisibleAndFrontmost(true); if (mImageId.notNull()) { texture_view->loadAsset(mImageId); @@ -2009,12 +2009,12 @@ void LLPanelProfileSecondLife::onShowTexturePicker() mImageId, LLUUID::null, mImageId, - FALSE, - FALSE, + false, + false, "SELECT PHOTO", PERM_NONE, PERM_NONE, - FALSE, + false, NULL); mFloaterTexturePickerHandle = texture_floaterp->getHandle(); @@ -2026,20 +2026,20 @@ void LLPanelProfileSecondLife::onShowTexturePicker() onCommitProfileImage(asset_id); } }); - texture_floaterp->setLocalTextureEnabled(FALSE); - texture_floaterp->setBakeTextureEnabled(FALSE); + texture_floaterp->setLocalTextureEnabled(false); + texture_floaterp->setBakeTextureEnabled(false); texture_floaterp->setCanApply(false, true, false); parent_floater->addDependentFloater(mFloaterTexturePickerHandle); texture_floaterp->openFloater(); - texture_floaterp->setFocus(TRUE); + texture_floaterp->setFocus(true); } } else { - floaterp->setMinimized(FALSE); - floaterp->setVisibleAndFrontmost(TRUE); + floaterp->setMinimized(false); + floaterp->setVisibleAndFrontmost(true); } } @@ -2145,7 +2145,7 @@ void LLPanelProfileWeb::updateData() { setIsLoading(); - mWebBrowser->setVisible(TRUE); + mWebBrowser->setVisible(true); mPerformanceTimer.start(); mWebBrowser->navigateTo(mURLWebProfile, HTTP_CONTENT_TEXT_HTML); } @@ -2182,7 +2182,7 @@ void LLPanelProfileWeb::onCommitLoad(LLUICtrl* ctrl) LLSD::String valstr = ctrl->getValue().asString(); if (valstr.empty()) { - mWebBrowser->setVisible(TRUE); + mWebBrowser->setVisible(true); mPerformanceTimer.start(); mWebBrowser->navigateTo( mURLHome, HTTP_CONTENT_TEXT_HTML ); } @@ -2277,7 +2277,7 @@ void LLPanelProfileFirstLife::onOpen(const LLSD& key) if (!getSelfProfile()) { // Otherwise as the only focusable element it will be selected - mDescriptionEdit->setTabStop(FALSE); + mDescriptionEdit->setTabStop(false); } resetData(); @@ -2344,12 +2344,12 @@ void LLPanelProfileFirstLife::onChangePhoto() mImageId, LLUUID::null, mImageId, - FALSE, - FALSE, + false, + false, "SELECT PHOTO", PERM_NONE, PERM_NONE, - FALSE, + false, NULL); mFloaterTexturePickerHandle = texture_floaterp->getHandle(); @@ -2361,19 +2361,19 @@ void LLPanelProfileFirstLife::onChangePhoto() onCommitPhoto(asset_id); } }); - texture_floaterp->setLocalTextureEnabled(FALSE); + texture_floaterp->setLocalTextureEnabled(false); texture_floaterp->setCanApply(false, true, false); parent_floater->addDependentFloater(mFloaterTexturePickerHandle); texture_floaterp->openFloater(); - texture_floaterp->setFocus(TRUE); + texture_floaterp->setFocus(true); } } else { - floaterp->setMinimized(FALSE); - floaterp->setVisibleAndFrontmost(TRUE); + floaterp->setMinimized(false); + floaterp->setVisibleAndFrontmost(true); } } @@ -2423,8 +2423,8 @@ void LLPanelProfileFirstLife::onCommitPhoto(const LLUUID& id) void LLPanelProfileFirstLife::setDescriptionText(const std::string &text) { - mSaveChanges->setEnabled(FALSE); - mDiscardChanges->setEnabled(FALSE); + mSaveChanges->setEnabled(false); + mDiscardChanges->setEnabled(false); mHasUnsavedChanges = false; mCurrentDescription = text; @@ -2433,8 +2433,8 @@ void LLPanelProfileFirstLife::setDescriptionText(const std::string &text) void LLPanelProfileFirstLife::onSetDescriptionDirty() { - mSaveChanges->setEnabled(TRUE); - mDiscardChanges->setEnabled(TRUE); + mSaveChanges->setEnabled(true); + mDiscardChanges->setEnabled(true); mHasUnsavedChanges = true; } @@ -2452,8 +2452,8 @@ void LLPanelProfileFirstLife::onSaveDescriptionChanges() LL_WARNS("AvatarProperties") << "Failed to update profile data, no cap found" << LL_ENDL; } - mSaveChanges->setEnabled(FALSE); - mDiscardChanges->setEnabled(FALSE); + mSaveChanges->setEnabled(false); + mDiscardChanges->setEnabled(false); mHasUnsavedChanges = false; } @@ -2499,8 +2499,8 @@ void LLPanelProfileFirstLife::setLoaded() if (getSelfProfile()) { - mDescriptionEdit->setEnabled(TRUE); - mPicture->setEnabled(TRUE); + mDescriptionEdit->setEnabled(true); + mPicture->setEnabled(true); mRemovePhoto->setEnabled(mImageId.notNull()); } } @@ -2566,8 +2566,8 @@ void LLPanelProfileNotes::onOpen(const LLSD& key) void LLPanelProfileNotes::setNotesText(const std::string &text) { - mSaveChanges->setEnabled(FALSE); - mDiscardChanges->setEnabled(FALSE); + mSaveChanges->setEnabled(false); + mDiscardChanges->setEnabled(false); mHasUnsavedChanges = false; mCurrentNotes = text; @@ -2576,8 +2576,8 @@ void LLPanelProfileNotes::setNotesText(const std::string &text) void LLPanelProfileNotes::onSetNotesDirty() { - mSaveChanges->setEnabled(TRUE); - mDiscardChanges->setEnabled(TRUE); + mSaveChanges->setEnabled(true); + mDiscardChanges->setEnabled(true); mHasUnsavedChanges = true; } @@ -2595,8 +2595,8 @@ void LLPanelProfileNotes::onSaveNotesChanges() LL_WARNS("AvatarProperties") << "Failed to update profile data, no cap found" << LL_ENDL; } - mSaveChanges->setEnabled(FALSE); - mDiscardChanges->setEnabled(FALSE); + mSaveChanges->setEnabled(false); + mDiscardChanges->setEnabled(false); mHasUnsavedChanges = false; } @@ -2608,7 +2608,7 @@ void LLPanelProfileNotes::onDiscardNotesChanges() void LLPanelProfileNotes::processProperties(LLAvatarNotes* avatar_notes) { setNotesText(avatar_notes->notes); - mNotesEditor->setEnabled(TRUE); + mNotesEditor->setEnabled(true); setLoaded(); } -- cgit v1.2.3 From 2117f8c4ba4565eef33f139a8c38b81f3c79648f Mon Sep 17 00:00:00 2001 From: Roxie Linden Date: Sun, 3 Mar 2024 15:50:35 -0800 Subject: Refactor for vivox spatial and p2p General refactoring to improve vivox spacial and p2p voice including generalizing voice info instead of just using sip uri and credentials. Voice server type is also passed around in the generalized voice info blob. --- indra/newview/llpanelprofile.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra/newview/llpanelprofile.cpp') diff --git a/indra/newview/llpanelprofile.cpp b/indra/newview/llpanelprofile.cpp index ffbed778c1..132b710620 100644 --- a/indra/newview/llpanelprofile.cpp +++ b/indra/newview/llpanelprofile.cpp @@ -1446,7 +1446,7 @@ void LLPanelProfileSecondLife::changed(U32 mask) } // virtual, called by LLVoiceClient -void LLPanelProfileSecondLife::onChange(EStatusType status, const std::string &channelURI, bool proximal) +void LLPanelProfileSecondLife::onChange(EStatusType status, const LLSD& channelInfo, bool proximal) { if(status == STATUS_JOINING || status == STATUS_LEFT_CHANNEL) { -- cgit v1.2.3 From f9473e8afcb624cc1b101195bf15943ec372b56f Mon Sep 17 00:00:00 2001 From: Alexander Gavriliuk Date: Mon, 6 May 2024 16:52:34 +0200 Subject: secondlife/viewer#1333 BOOL to bool conversion leftovers: ternaries --- indra/newview/llpanelprofile.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'indra/newview/llpanelprofile.cpp') diff --git a/indra/newview/llpanelprofile.cpp b/indra/newview/llpanelprofile.cpp index 3a26fb086b..0fc2ad4d6d 100644 --- a/indra/newview/llpanelprofile.cpp +++ b/indra/newview/llpanelprofile.cpp @@ -779,11 +779,11 @@ void LLFloaterProfilePermissions::fillRightsData() { S32 rights = relation->getRightsGrantedTo(); - bool see_online = LLRelationship::GRANT_ONLINE_STATUS & rights ? true : false; + bool see_online = LLRelationship::GRANT_ONLINE_STATUS & rights; mOnlineStatus->setValue(see_online); mMapRights->setEnabled(see_online); - mMapRights->setValue(LLRelationship::GRANT_MAP_LOCATION & rights ? true : false); - mEditObjectRights->setValue(LLRelationship::GRANT_MODIFY_OBJECTS & rights ? true : false); + mMapRights->setValue(LLRelationship::GRANT_MAP_LOCATION & rights); + mEditObjectRights->setValue(LLRelationship::GRANT_MODIFY_OBJECTS & rights); } else { @@ -798,7 +798,7 @@ void LLFloaterProfilePermissions::rightsConfirmationCallback(const LLSD& notific S32 option = LLNotificationsUtil::getSelectedOption(notification, response); if (option != 0) // canceled { - mEditObjectRights->setValue(mEditObjectRights->getValue().asBoolean() ? false : true); + mEditObjectRights->setValue(!mEditObjectRights->getValue().asBoolean()); } else { @@ -824,7 +824,7 @@ void LLFloaterProfilePermissions::onCommitSeeOnlineRights() if (relation) { S32 rights = relation->getRightsGrantedTo(); - mMapRights->setValue(LLRelationship::GRANT_MAP_LOCATION & rights ? true : false); + mMapRights->setValue(LLRelationship::GRANT_MAP_LOCATION & rights); } else { -- cgit v1.2.3 From e2e37cced861b98de8c1a7c9c0d3a50d2d90e433 Mon Sep 17 00:00:00 2001 From: Ansariel Date: Wed, 22 May 2024 21:25:21 +0200 Subject: Fix line endlings --- indra/newview/llpanelprofile.cpp | 4862 +++++++++++++++++++------------------- 1 file changed, 2431 insertions(+), 2431 deletions(-) (limited to 'indra/newview/llpanelprofile.cpp') diff --git a/indra/newview/llpanelprofile.cpp b/indra/newview/llpanelprofile.cpp index adceee80d3..579f0941c3 100644 --- a/indra/newview/llpanelprofile.cpp +++ b/indra/newview/llpanelprofile.cpp @@ -1,2431 +1,2431 @@ -/** -* @file llpanelprofile.cpp -* @brief Profile panel implementation -* -* $LicenseInfo:firstyear=2022&license=viewerlgpl$ -* Second Life Viewer Source Code -* Copyright (C) 2022, 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$ -*/ - -#include "llviewerprecompiledheaders.h" -#include "llpanelprofile.h" - -// Common -#include "llavatarnamecache.h" -#include "llsdutil.h" -#include "llslurl.h" -#include "lldateutil.h" //ageFromDate - -// UI -#include "llavatariconctrl.h" -#include "llclipboard.h" -#include "llcheckboxctrl.h" -#include "llcombobox.h" -#include "lllineeditor.h" -#include "llloadingindicator.h" -#include "llmenubutton.h" -#include "lltabcontainer.h" -#include "lltextbox.h" -#include "lltexteditor.h" -#include "lltexturectrl.h" -#include "lltoggleablemenu.h" -#include "lltooldraganddrop.h" -#include "llgrouplist.h" -#include "llurlaction.h" - -// Image -#include "llimagej2c.h" - -// Newview -#include "llagent.h" //gAgent -#include "llagentpicksinfo.h" -#include "llavataractions.h" -#include "llavatarpropertiesprocessor.h" -#include "llcallingcard.h" -#include "llcommandhandler.h" -#include "llfloaterprofiletexture.h" -#include "llfloaterreg.h" -#include "llfloaterreporter.h" -#include "llfilepicker.h" -#include "llfirstuse.h" -#include "llgroupactions.h" -#include "lllogchat.h" -#include "llmutelist.h" -#include "llnotificationsutil.h" -#include "llpanelblockedlist.h" -#include "llpanelprofileclassifieds.h" -#include "llpanelprofilepicks.h" -#include "lltrans.h" -#include "llviewercontrol.h" -#include "llviewermenu.h" //is_agent_mappable -#include "llviewermenufile.h" -#include "llviewertexturelist.h" -#include "llvoiceclient.h" -#include "llweb.h" - - -static LLPanelInjector t_panel_profile_secondlife("panel_profile_secondlife"); -static LLPanelInjector t_panel_web("panel_profile_web"); -static LLPanelInjector t_panel_picks("panel_profile_picks"); -static LLPanelInjector t_panel_firstlife("panel_profile_firstlife"); -static LLPanelInjector t_panel_notes("panel_profile_notes"); -static LLPanelInjector t_panel_profile("panel_profile"); - -static const std::string PANEL_SECONDLIFE = "panel_profile_secondlife"; -static const std::string PANEL_WEB = "panel_profile_web"; -static const std::string PANEL_PICKS = "panel_profile_picks"; -static const std::string PANEL_CLASSIFIEDS = "panel_profile_classifieds"; -static const std::string PANEL_FIRSTLIFE = "panel_profile_firstlife"; -static const std::string PANEL_NOTES = "panel_profile_notes"; -static const std::string PANEL_PROFILE_VIEW = "panel_profile_view"; - -static const std::string PROFILE_PROPERTIES_CAP = "AgentProfile"; -static const std::string PROFILE_IMAGE_UPLOAD_CAP = "UploadAgentProfileImage"; - - -////////////////////////////////////////////////////////////////////////// - -LLUUID post_profile_image(std::string cap_url, const LLSD &first_data, std::string path_to_image, LLHandle *handle) -{ - LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID); - LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t - httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("post_profile_image_coro", httpPolicy)); - LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest); - LLCore::HttpHeaders::ptr_t httpHeaders; - - LLCore::HttpOptions::ptr_t httpOpts(new LLCore::HttpOptions); - httpOpts->setFollowRedirects(true); - - LLSD result = httpAdapter->postAndSuspend(httpRequest, cap_url, first_data, httpOpts, httpHeaders); - - LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS]; - LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults); - - if (!status) - { - // todo: notification? - LL_WARNS("AvatarProperties") << "Failed to get uploader cap " << status.toString() << LL_ENDL; - return LLUUID::null; - } - if (!result.has("uploader")) - { - // todo: notification? - LL_WARNS("AvatarProperties") << "Failed to get uploader cap, response contains no data." << LL_ENDL; - 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; - return LLUUID::null; - } - - // Upload the image - LLCore::HttpRequest::ptr_t uploaderhttpRequest(new LLCore::HttpRequest); - LLCore::HttpHeaders::ptr_t uploaderhttpHeaders(new LLCore::HttpHeaders); - LLCore::HttpOptions::ptr_t uploaderhttpOpts(new LLCore::HttpOptions); - S64 length; - - { - llifstream instream(path_to_image.c_str(), std::iostream::binary | std::iostream::ate); - if (!instream.is_open()) - { - LL_WARNS("AvatarProperties") << "Failed to open file " << path_to_image << LL_ENDL; - return LLUUID::null; - } - length = instream.tellg(); - } - - uploaderhttpHeaders->append(HTTP_OUT_HEADER_CONTENT_TYPE, "application/jp2"); // optional - uploaderhttpHeaders->append(HTTP_OUT_HEADER_CONTENT_LENGTH, llformat("%d", length)); // required! - uploaderhttpOpts->setFollowRedirects(true); - - result = httpAdapter->postFileAndSuspend(uploaderhttpRequest, uploader_cap, path_to_image, uploaderhttpOpts, uploaderhttpHeaders); - - httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS]; - status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults); - - LL_DEBUGS("AvatarProperties") << result << LL_ENDL; - - if (!status) - { - LL_WARNS("AvatarProperties") << "Failed to upload image " << status.toString() << LL_ENDL; - return LLUUID::null; - } - - if (result["state"].asString() != "complete") - { - if (result.has("message")) - { - LL_WARNS("AvatarProperties") << "Failed to upload image, state " << result["state"] << " message: " << result["message"] << LL_ENDL; - } - else - { - LL_WARNS("AvatarProperties") << "Failed to upload image " << result << LL_ENDL; - } - 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 *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 - if (!handle->isDead()) - { - switch (type) - { - case PROFILE_IMAGE_SL: - { - LLPanelProfileSecondLife* panel = static_cast(handle->get()); - if (result.notNull()) - { - panel->setProfileImageUploaded(result); - } - else - { - // failure, just stop progress indicator - panel->setProfileImageUploading(false); - } - break; - } - case PROFILE_IMAGE_FL: - { - LLPanelProfileFirstLife* panel = static_cast(handle->get()); - if (result.notNull()) - { - panel->setProfileImageUploaded(result); - } - else - { - // failure, just stop progress indicator - panel->setProfileImageUploading(false); - } - break; - } - } - } - - if (type == PROFILE_IMAGE_SL && result.notNull()) - { - LLAvatarIconIDCache::getInstance()->add(gAgentID, result); - // Should trigger callbacks in icon controls - LLAvatarPropertiesProcessor::getInstance()->sendAvatarPropertiesRequest(gAgentID); - } - - // Cleanup - LLFile::remove(path_to_image); - delete handle; -} - -////////////////////////////////////////////////////////////////////////// -// LLProfileHandler - -class LLProfileHandler : public LLCommandHandler -{ -public: - // requires trusted browser to trigger - LLProfileHandler() : LLCommandHandler("profile", UNTRUSTED_THROTTLE) { } - - bool handle(const LLSD& params, - const LLSD& query_map, - const std::string& grid, - LLMediaCtrl* web) - { - if (params.size() < 1) return false; - std::string agent_name = params[0]; - LL_INFOS() << "Profile, agent_name " << agent_name << LL_ENDL; - std::string url = getProfileURL(agent_name); - LLWeb::loadURLInternal(url); - - return true; - } -}; -LLProfileHandler gProfileHandler; - - -////////////////////////////////////////////////////////////////////////// -// LLAgentHandler - -class LLAgentHandler : public LLCommandHandler -{ -public: - // requires trusted browser to trigger - LLAgentHandler() : LLCommandHandler("agent", UNTRUSTED_THROTTLE) { } - - virtual bool canHandleUntrusted( - const LLSD& params, - const LLSD& query_map, - LLMediaCtrl* web, - const std::string& nav_type) - { - if (params.size() < 2) - { - return true; // don't block, will fail later - } - - if (nav_type == NAV_TYPE_CLICKED - || nav_type == NAV_TYPE_EXTERNAL) - { - return true; - } - - const std::string verb = params[1].asString(); - if (verb == "about" || verb == "inspect" || verb == "reportAbuse") - { - return true; - } - return false; - } - - bool handle(const LLSD& params, - const LLSD& query_map, - const std::string& grid, - LLMediaCtrl* web) - { - if (params.size() < 2) return false; - LLUUID avatar_id; - if (!avatar_id.set(params[0], false)) - { - return false; - } - - const std::string verb = params[1].asString(); - if (verb == "about") - { - LLAvatarActions::showProfile(avatar_id); - return true; - } - - if (verb == "inspect") - { - LLFloaterReg::showInstance("inspect_avatar", LLSD().with("avatar_id", avatar_id)); - return true; - } - - if (verb == "im") - { - LLAvatarActions::startIM(avatar_id); - return true; - } - - if (verb == "pay") - { - if (!LLUI::getInstance()->mSettingGroups["config"]->getBOOL("EnableAvatarPay")) - { - LLNotificationsUtil::add("NoAvatarPay", LLSD(), LLSD(), std::string("SwitchToStandardSkinAndQuit")); - return true; - } - - LLAvatarActions::pay(avatar_id); - return true; - } - - if (verb == "offerteleport") - { - LLAvatarActions::offerTeleport(avatar_id); - return true; - } - - if (verb == "requestfriend") - { - LLAvatarActions::requestFriendshipDialog(avatar_id); - return true; - } - - if (verb == "removefriend") - { - LLAvatarActions::removeFriendDialog(avatar_id); - return true; - } - - if (verb == "mute") - { - if (! LLAvatarActions::isBlocked(avatar_id)) - { - LLAvatarActions::toggleBlock(avatar_id); - } - return true; - } - - if (verb == "unmute") - { - if (LLAvatarActions::isBlocked(avatar_id)) - { - LLAvatarActions::toggleBlock(avatar_id); - } - return true; - } - - if (verb == "block") - { - if (params.size() > 2) - { - const std::string object_name = LLURI::unescape(params[2].asString()); - LLMute mute(avatar_id, object_name, LLMute::OBJECT); - LLMuteList::getInstance()->add(mute); - LLPanelBlockedList::showPanelAndSelect(mute.mID); - } - return true; - } - - if (verb == "unblock") - { - if (params.size() > 2) - { - const std::string object_name = params[2].asString(); - LLMute mute(avatar_id, object_name, LLMute::OBJECT); - LLMuteList::getInstance()->remove(mute); - } - return true; - } - - // reportAbuse is here due to convoluted avatar handling - // in LLScrollListCtrl and LLTextBase - if (verb == "reportAbuse" && web == NULL) - { - LLAvatarName av_name; - if (LLAvatarNameCache::get(avatar_id, &av_name)) - { - LLFloaterReporter::showFromAvatar(avatar_id, av_name.getCompleteName()); - } - else - { - LLFloaterReporter::showFromAvatar(avatar_id, "not avaliable"); - } - return true; - } - return false; - } -}; -LLAgentHandler gAgentHandler; - - -///---------------------------------------------------------------------------- -/// LLFloaterProfilePermissions -///---------------------------------------------------------------------------- - -class LLFloaterProfilePermissions - : public LLFloater - , public LLFriendObserver -{ -public: - LLFloaterProfilePermissions(LLView * owner, const LLUUID &avatar_id); - ~LLFloaterProfilePermissions(); - bool postBuild() override; - void onOpen(const LLSD& key) override; - void draw() override; - void changed(U32 mask) override; // LLFriendObserver - - void onAvatarNameCache(const LLUUID& agent_id, const LLAvatarName& av_name); - bool hasUnsavedChanges() { return mHasUnsavedPermChanges; } - - void onApplyRights(); - -private: - void fillRightsData(); - void rightsConfirmationCallback(const LLSD& notification, const LLSD& response); - void confirmModifyRights(bool grant); - void onCommitSeeOnlineRights(); - void onCommitEditRights(); - void onCancel(); - - LLTextBase* mDescription; - LLCheckBoxCtrl* mOnlineStatus; - LLCheckBoxCtrl* mMapRights; - LLCheckBoxCtrl* mEditObjectRights; - LLButton* mOkBtn; - LLButton* mCancelBtn; - - LLUUID mAvatarID; - F32 mContextConeOpacity; - bool mHasUnsavedPermChanges; - LLHandle mOwnerHandle; - - boost::signals2::connection mAvatarNameCacheConnection; -}; - -LLFloaterProfilePermissions::LLFloaterProfilePermissions(LLView * owner, const LLUUID &avatar_id) - : LLFloater(LLSD()) - , mAvatarID(avatar_id) - , mContextConeOpacity(0.0f) - , mHasUnsavedPermChanges(false) - , mOwnerHandle(owner->getHandle()) -{ - buildFromFile("floater_profile_permissions.xml"); -} - -LLFloaterProfilePermissions::~LLFloaterProfilePermissions() -{ - mAvatarNameCacheConnection.disconnect(); - if (mAvatarID.notNull()) - { - LLAvatarTracker::instance().removeParticularFriendObserver(mAvatarID, this); - } -} - -bool LLFloaterProfilePermissions::postBuild() -{ - mDescription = getChild("perm_description"); - mOnlineStatus = getChild("online_check"); - mMapRights = getChild("map_check"); - mEditObjectRights = getChild("objects_check"); - mOkBtn = getChild("perms_btn_ok"); - mCancelBtn = getChild("perms_btn_cancel"); - - mOnlineStatus->setCommitCallback([this](LLUICtrl*, void*) { onCommitSeeOnlineRights(); }, nullptr); - mMapRights->setCommitCallback([this](LLUICtrl*, void*) { mHasUnsavedPermChanges = true; }, nullptr); - mEditObjectRights->setCommitCallback([this](LLUICtrl*, void*) { onCommitEditRights(); }, nullptr); - mOkBtn->setCommitCallback([this](LLUICtrl*, void*) { onApplyRights(); }, nullptr); - mCancelBtn->setCommitCallback([this](LLUICtrl*, void*) { onCancel(); }, nullptr); - - return true; -} - -void LLFloaterProfilePermissions::onOpen(const LLSD& key) -{ - if (LLAvatarActions::isFriend(mAvatarID)) - { - LLAvatarTracker::instance().addParticularFriendObserver(mAvatarID, this); - fillRightsData(); - } - - mCancelBtn->setFocus(true); - - mAvatarNameCacheConnection = LLAvatarNameCache::get(mAvatarID, boost::bind(&LLFloaterProfilePermissions::onAvatarNameCache, this, _1, _2)); -} - -void LLFloaterProfilePermissions::draw() -{ - // drawFrustum - LLView *owner = mOwnerHandle.get(); - static LLCachedControl max_opacity(gSavedSettings, "PickerContextOpacity", 0.4f); - drawConeToOwner(mContextConeOpacity, max_opacity, owner); - LLFloater::draw(); -} - -void LLFloaterProfilePermissions::changed(U32 mask) -{ - if (mask != LLFriendObserver::ONLINE) - { - fillRightsData(); - } -} - -void LLFloaterProfilePermissions::onAvatarNameCache(const LLUUID& agent_id, const LLAvatarName& av_name) -{ - mAvatarNameCacheConnection.disconnect(); - - LLStringUtil::format_map_t args; - args["[AGENT_NAME]"] = av_name.getDisplayName(); - std::string descritpion = getString("description_string", args); - mDescription->setValue(descritpion); -} - -void LLFloaterProfilePermissions::fillRightsData() -{ - const LLRelationship* relation = LLAvatarTracker::instance().getBuddyInfo(mAvatarID); - // If true - we are viewing friend's profile, enable check boxes and set values. - if (relation) - { - S32 rights = relation->getRightsGrantedTo(); - - bool see_online = LLRelationship::GRANT_ONLINE_STATUS & rights; - mOnlineStatus->setValue(see_online); - mMapRights->setEnabled(see_online); - mMapRights->setValue(LLRelationship::GRANT_MAP_LOCATION & rights); - mEditObjectRights->setValue(LLRelationship::GRANT_MODIFY_OBJECTS & rights); - } - else - { - closeFloater(); - LL_INFOS("ProfilePermissions") << "Floater closing since agent is no longer a friend" << LL_ENDL; - } -} - -void LLFloaterProfilePermissions::rightsConfirmationCallback(const LLSD& notification, - const LLSD& response) -{ - S32 option = LLNotificationsUtil::getSelectedOption(notification, response); - if (option != 0) // canceled - { - mEditObjectRights->setValue(!mEditObjectRights->getValue().asBoolean()); - } - else - { - mHasUnsavedPermChanges = true; - } -} - -void LLFloaterProfilePermissions::confirmModifyRights(bool grant) -{ - LLSD args; - args["NAME"] = LLSLURL("agent", mAvatarID, "completename").getSLURLString(); - LLNotificationsUtil::add(grant ? "GrantModifyRights" : "RevokeModifyRights", args, LLSD(), - boost::bind(&LLFloaterProfilePermissions::rightsConfirmationCallback, this, _1, _2)); -} - -void LLFloaterProfilePermissions::onCommitSeeOnlineRights() -{ - bool see_online = mOnlineStatus->getValue().asBoolean(); - mMapRights->setEnabled(see_online); - if (see_online) - { - const LLRelationship* relation = LLAvatarTracker::instance().getBuddyInfo(mAvatarID); - if (relation) - { - S32 rights = relation->getRightsGrantedTo(); - mMapRights->setValue(LLRelationship::GRANT_MAP_LOCATION & rights); - } - else - { - closeFloater(); - LL_INFOS("ProfilePermissions") << "Floater closing since agent is no longer a friend" << LL_ENDL; - } - } - else - { - mMapRights->setValue(false); - } - mHasUnsavedPermChanges = true; -} - -void LLFloaterProfilePermissions::onCommitEditRights() -{ - const LLRelationship* buddy_relationship = LLAvatarTracker::instance().getBuddyInfo(mAvatarID); - - if (!buddy_relationship) - { - LL_WARNS("ProfilePermissions") << "Trying to modify rights for non-friend avatar. Closing floater." << LL_ENDL; - closeFloater(); - return; - } - - bool allow_modify_objects = mEditObjectRights->getValue().asBoolean(); - - // if modify objects checkbox clicked - if (buddy_relationship->isRightGrantedTo( - LLRelationship::GRANT_MODIFY_OBJECTS) != allow_modify_objects) - { - confirmModifyRights(allow_modify_objects); - } -} - -void LLFloaterProfilePermissions::onApplyRights() -{ - const LLRelationship* buddy_relationship = LLAvatarTracker::instance().getBuddyInfo(mAvatarID); - - if (!buddy_relationship) - { - LL_WARNS("ProfilePermissions") << "Trying to modify rights for non-friend avatar. Skipped." << LL_ENDL; - return; - } - - S32 rights = 0; - - if (mOnlineStatus->getValue().asBoolean()) - { - rights |= LLRelationship::GRANT_ONLINE_STATUS; - } - if (mMapRights->getValue().asBoolean()) - { - rights |= LLRelationship::GRANT_MAP_LOCATION; - } - if (mEditObjectRights->getValue().asBoolean()) - { - rights |= LLRelationship::GRANT_MODIFY_OBJECTS; - } - - LLAvatarPropertiesProcessor::getInstance()->sendFriendRights(mAvatarID, rights); - - closeFloater(); -} - -void LLFloaterProfilePermissions::onCancel() -{ - closeFloater(); -} - -////////////////////////////////////////////////////////////////////////// -// LLPanelProfileSecondLife - -LLPanelProfileSecondLife::LLPanelProfileSecondLife() - : LLPanelProfilePropertiesProcessorTab() - , mAvatarNameCacheConnection() - , mHasUnsavedDescriptionChanges(false) - , mWaitingForImageUpload(false) - , mAllowPublish(false) - , mHideAge(false) -{ -} - -LLPanelProfileSecondLife::~LLPanelProfileSecondLife() -{ - if (getAvatarId().notNull()) - { - LLAvatarTracker::instance().removeParticularFriendObserver(getAvatarId(), this); - } - - if (LLVoiceClient::instanceExists()) - { - LLVoiceClient::getInstance()->removeObserver((LLVoiceClientStatusObserver*)this); - } - - if (mAvatarNameCacheConnection.connected()) - { - mAvatarNameCacheConnection.disconnect(); - } -} - -bool LLPanelProfileSecondLife::postBuild() -{ - mGroupList = getChild("group_list"); - mShowInSearchCombo = getChild("show_in_search"); - mHideAgeCombo = getChild("hide_age"); - mSecondLifePic = getChild("2nd_life_pic"); - mSecondLifePicLayout = getChild("image_panel"); - mDescriptionEdit = getChild("sl_description_edit"); - mAgentActionMenuButton = getChild("agent_actions_menu"); - mSaveDescriptionChanges = getChild("save_description_changes"); - mDiscardDescriptionChanges = getChild("discard_description_changes"); - mCanSeeOnlineIcon = getChild("can_see_online"); - mCantSeeOnlineIcon = getChild("cant_see_online"); - mCanSeeOnMapIcon = getChild("can_see_on_map"); - mCantSeeOnMapIcon = getChild("cant_see_on_map"); - mCanEditObjectsIcon = getChild("can_edit_objects"); - mCantEditObjectsIcon = getChild("cant_edit_objects"); - - mShowInSearchCombo->setCommitCallback([this](LLUICtrl*, void*) { onShowInSearchCallback(); }, nullptr); - mHideAgeCombo->setCommitCallback([this](LLUICtrl*, void*) { onHideAgeCallback(); }, nullptr); - 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); - mDescriptionEdit->setKeystrokeCallback([this](LLTextEditor* caller) { onSetDescriptionDirty(); }); - - mCanSeeOnlineIcon->setMouseUpCallback([this](LLUICtrl*, S32 x, S32 y, MASK mask) { onShowAgentPermissionsDialog(); }); - mCantSeeOnlineIcon->setMouseUpCallback([this](LLUICtrl*, S32 x, S32 y, MASK mask) { onShowAgentPermissionsDialog(); }); - mCanSeeOnMapIcon->setMouseUpCallback([this](LLUICtrl*, S32 x, S32 y, MASK mask) { onShowAgentPermissionsDialog(); }); - mCantSeeOnMapIcon->setMouseUpCallback([this](LLUICtrl*, S32 x, S32 y, MASK mask) { onShowAgentPermissionsDialog(); }); - mCanEditObjectsIcon->setMouseUpCallback([this](LLUICtrl*, S32 x, S32 y, MASK mask) { onShowAgentPermissionsDialog(); }); - mCantEditObjectsIcon->setMouseUpCallback([this](LLUICtrl*, S32 x, S32 y, MASK mask) { onShowAgentPermissionsDialog(); }); - mSecondLifePic->setMouseUpCallback([this](LLUICtrl*, S32 x, S32 y, MASK mask) { onShowAgentProfileTexture(); }); - - return true; -} - -void LLPanelProfileSecondLife::onOpen(const LLSD& key) -{ - LLPanelProfileTab::onOpen(key); - - resetData(); - - LLUUID avatar_id = getAvatarId(); - - bool own_profile = getSelfProfile(); - - mGroupList->setShowNone(!own_profile); - - childSetVisible("notes_panel", !own_profile); - childSetVisible("settings_panel", own_profile); - childSetVisible("about_buttons_panel", own_profile); - - if (own_profile) - { - // Group list control cannot toggle ForAgent loading - // Less than ideal, but viewing own profile via search is edge case - mGroupList->enableForAgent(false); - } - - // Init menu, menu needs to be created in scope of a registar to work correctly. - LLUICtrl::CommitCallbackRegistry::ScopedRegistrar commit; - commit.add("Profile.Commit", [this](LLUICtrl*, const LLSD& userdata) { onCommitMenu(userdata); }); - - LLUICtrl::EnableCallbackRegistry::ScopedRegistrar enable; - enable.add("Profile.EnableItem", [this](LLUICtrl*, const LLSD& userdata) { return onEnableMenu(userdata); }); - enable.add("Profile.CheckItem", [this](LLUICtrl*, const LLSD& userdata) { return onCheckMenu(userdata); }); - - if (own_profile) - { - mAgentActionMenuButton->setMenu("menu_profile_self.xml", LLMenuButton::MP_BOTTOM_RIGHT); - } - else - { - // Todo: use PeopleContextMenu instead? - mAgentActionMenuButton->setMenu("menu_profile_other.xml", LLMenuButton::MP_BOTTOM_RIGHT); - } - - mDescriptionEdit->setParseHTML(!own_profile); - - if (!own_profile) - { - mVoiceStatus = LLAvatarActions::canCall() && (LLAvatarActions::isFriend(avatar_id) ? LLAvatarTracker::instance().isBuddyOnline(avatar_id) : true); - updateOnlineStatus(); - fillRightsData(); - } - - mAvatarNameCacheConnection = LLAvatarNameCache::get(getAvatarId(), boost::bind(&LLPanelProfileSecondLife::onAvatarNameCache, this, _1, _2)); -} - - -bool LLPanelProfileSecondLife::handleDragAndDrop(S32 x, S32 y, MASK mask, bool drop, - EDragAndDropType cargo_type, - void* cargo_data, - EAcceptance* accept, - std::string& tooltip_msg) -{ - // Try children first - if (LLPanelProfileTab::handleDragAndDrop(x, y, mask, drop, cargo_type, cargo_data, accept, tooltip_msg) - && *accept != ACCEPT_NO) - { - return true; - } - - // No point sharing with own profile - if (getSelfProfile()) - { - return false; - } - - // Exclude fields that look like they are editable. - S32 child_x = 0; - S32 child_y = 0; - if (localPointToOtherView(x, y, &child_x, &child_y, mDescriptionEdit) - && mDescriptionEdit->pointInView(child_x, child_y)) - { - return false; - } - - if (localPointToOtherView(x, y, &child_x, &child_y, mGroupList) - && mGroupList->pointInView(child_x, child_y)) - { - return false; - } - - // Share - LLToolDragAndDrop::handleGiveDragAndDrop(getAvatarId(), - LLUUID::null, - drop, - cargo_type, - cargo_data, - accept); - return true; -} - -void LLPanelProfileSecondLife::refreshName() -{ - if (!mAvatarNameCacheConnection.connected()) - { - mAvatarNameCacheConnection = LLAvatarNameCache::get(getAvatarId(), boost::bind(&LLPanelProfileSecondLife::onAvatarNameCache, this, _1, _2)); - } -} - -void LLPanelProfileSecondLife::resetData() -{ - resetLoading(); - - // Set default image and 1:1 dimensions for it - mSecondLifePic->setValue("Generic_Person_Large"); - - LLRect imageRect = mSecondLifePicLayout->getRect(); - mSecondLifePicLayout->reshape(imageRect.getWidth(), imageRect.getWidth()); - - setDescriptionText(LLStringUtil::null); - mGroups.clear(); - mGroupList->setGroups(mGroups); - - bool own_profile = getSelfProfile(); - mCanSeeOnlineIcon->setVisible(false); - mCantSeeOnlineIcon->setVisible(!own_profile); - mCanSeeOnMapIcon->setVisible(false); - mCantSeeOnMapIcon->setVisible(!own_profile); - mCanEditObjectsIcon->setVisible(false); - mCantEditObjectsIcon->setVisible(!own_profile); - - mCanSeeOnlineIcon->setEnabled(false); - mCantSeeOnlineIcon->setEnabled(false); - mCanSeeOnMapIcon->setEnabled(false); - mCantSeeOnMapIcon->setEnabled(false); - mCanEditObjectsIcon->setEnabled(false); - mCantEditObjectsIcon->setEnabled(false); - - childSetVisible("partner_layout", false); - childSetVisible("badge_layout", false); - childSetVisible("partner_spacer_layout", true); -} - -void LLPanelProfileSecondLife::processProperties(void* data, EAvatarProcessorType type) -{ - if (APT_PROPERTIES == type) - { - LLAvatarData* avatar_data = static_cast(data); - if (avatar_data && getAvatarId() == avatar_data->avatar_id) - { - processProfileProperties(avatar_data); - } - } -} - -void LLPanelProfileSecondLife::processProfileProperties(const LLAvatarData* avatar_data) -{ - const LLRelationship* relationship = LLAvatarTracker::instance().getBuddyInfo(getAvatarId()); - if ((relationship != NULL || gAgent.isGodlike()) && !getSelfProfile()) - { - // Relies onto friend observer to get information about online status updates. - // Once SL-17506 gets implemented, condition might need to become: - // (gAgent.isGodlike() || isRightGrantedFrom || flags & AVATAR_ONLINE) - processOnlineStatus(relationship != NULL, - gAgent.isGodlike() || relationship->isRightGrantedFrom(LLRelationship::GRANT_ONLINE_STATUS), - (avatar_data->flags & AVATAR_ONLINE)); - } - - fillCommonData(avatar_data); - - fillPartnerData(avatar_data); - - fillAccountStatus(avatar_data); - - LLAvatarData::group_list_t::const_iterator it = avatar_data->group_list.begin(); - const LLAvatarData::group_list_t::const_iterator it_end = avatar_data->group_list.end(); - - for (; it_end != it; ++it) - { - LLAvatarData::LLGroupData group_data = *it; - mGroups[group_data.group_name] = group_data.group_id; - } - - mGroupList->setGroups(mGroups); - - setLoaded(); -} - -void LLPanelProfileSecondLife::openGroupProfile() -{ - LLUUID group_id = mGroupList->getSelectedUUID(); - LLGroupActions::show(group_id); -} - -void LLPanelProfileSecondLife::onAvatarNameCache(const LLUUID& agent_id, const LLAvatarName& av_name) -{ - mAvatarNameCacheConnection.disconnect(); - getChild("display_name")->setValue(av_name.getDisplayName()); - getChild("user_name")->setValue(av_name.getAccountName()); -} - -void LLPanelProfileSecondLife::setProfileImageUploading(bool loading) -{ - LLLoadingIndicator* indicator = getChild("image_upload_indicator"); - indicator->setVisible(loading); - if (loading) - { - indicator->start(); - } - else - { - indicator->stop(); - } - mWaitingForImageUpload = loading; -} - -void LLPanelProfileSecondLife::setProfileImageUploaded(const LLUUID &image_asset_id) -{ - mSecondLifePic->setValue(image_asset_id); - - LLFloater *floater = mFloaterProfileTextureHandle.get(); - if (floater) - { - LLFloaterProfileTexture * texture_view = dynamic_cast(floater); - texture_view->loadAsset(mSecondLifePic->getImageAssetId()); - } - - setProfileImageUploading(false); -} - -bool LLPanelProfileSecondLife::hasUnsavedChanges() -{ - LLFloater *floater = mFloaterPermissionsHandle.get(); - if (floater) - { - LLFloaterProfilePermissions* perm = dynamic_cast(floater); - if (perm && perm->hasUnsavedChanges()) - { - return true; - } - } - // if floater - return mHasUnsavedDescriptionChanges; -} - -void LLPanelProfileSecondLife::commitUnsavedChanges() -{ - LLFloater *floater = mFloaterPermissionsHandle.get(); - if (floater) - { - LLFloaterProfilePermissions* perm = dynamic_cast(floater); - if (perm && perm->hasUnsavedChanges()) - { - perm->onApplyRights(); - } - } - if (mHasUnsavedDescriptionChanges) - { - onSaveDescriptionChanges(); - } -} - -void LLPanelProfileSecondLife::fillCommonData(const LLAvatarData* avatar_data) -{ - // Refresh avatar id in cache with new info to prevent re-requests - // and to make sure icons in text will be up to date - LLAvatarIconIDCache::getInstance()->add(avatar_data->avatar_id, avatar_data->image_id); - - fillAgeData(avatar_data); - - setDescriptionText(avatar_data->about_text); - - mSecondLifePic->setValue(avatar_data->image_id); - - if (getSelfProfile()) - { - mAllowPublish = avatar_data->flags & AVATAR_ALLOW_PUBLISH; - mShowInSearchCombo->setValue(mAllowPublish); - } -} - -void LLPanelProfileSecondLife::fillPartnerData(const LLAvatarData* avatar_data) -{ - LLTextBox* partner_text_ctrl = getChild("partner_link"); - if (avatar_data->partner_id.notNull()) - { - childSetVisible("partner_layout", true); - LLStringUtil::format_map_t args; - args["[LINK]"] = LLSLURL("agent", avatar_data->partner_id, "inspect").getSLURLString(); - std::string partner_text = getString("partner_text", args); - partner_text_ctrl->setText(partner_text); - } - else - { - childSetVisible("partner_layout", false); - } -} - -void LLPanelProfileSecondLife::fillAccountStatus(const LLAvatarData* avatar_data) -{ - LLStringUtil::format_map_t args; - args["[ACCTTYPE]"] = LLAvatarPropertiesProcessor::accountType(avatar_data); - args["[PAYMENTINFO]"] = LLAvatarPropertiesProcessor::paymentInfo(avatar_data); - - std::string caption_text = getString("CaptionTextAcctInfo", args); - getChild("account_info")->setValue(caption_text); - - const S32 LINDEN_EMPLOYEE_INDEX = 3; - LLDate sl_release; - sl_release.fromYMDHMS(2003, 6, 23, 0, 0, 0); - std::string customer_lower = avatar_data->customer_type; - LLStringUtil::toLower(customer_lower); - if (avatar_data->caption_index == LINDEN_EMPLOYEE_INDEX) - { - getChild("badge_icon")->setValue("Profile_Badge_Linden"); - getChild("badge_text")->setValue(getString("BadgeLinden")); - childSetVisible("badge_layout", true); - childSetVisible("partner_spacer_layout", false); - } - else if (avatar_data->born_on < sl_release) - { - getChild("badge_icon")->setValue("Profile_Badge_Beta"); - getChild("badge_text")->setValue(getString("BadgeBeta")); - childSetVisible("badge_layout", true); - childSetVisible("partner_spacer_layout", false); - } - else if (customer_lower == "beta_lifetime") - { - getChild("badge_icon")->setValue("Profile_Badge_Beta_Lifetime"); - getChild("badge_text")->setValue(getString("BadgeBetaLifetime")); - childSetVisible("badge_layout", true); - childSetVisible("partner_spacer_layout", false); - } - else if (customer_lower == "lifetime") - { - getChild("badge_icon")->setValue("Profile_Badge_Lifetime"); - getChild("badge_text")->setValue(getString("BadgeLifetime")); - childSetVisible("badge_layout", true); - childSetVisible("partner_spacer_layout", false); - } - else if (customer_lower == "secondlifetime_premium") - { - getChild("badge_icon")->setValue("Profile_Badge_Premium_Lifetime"); - getChild("badge_text")->setValue(getString("BadgePremiumLifetime")); - childSetVisible("badge_layout", true); - childSetVisible("partner_spacer_layout", false); - } - else if (customer_lower == "secondlifetime_premium_plus") - { - getChild("badge_icon")->setValue("Profile_Badge_Pplus_Lifetime"); - getChild("badge_text")->setValue(getString("BadgePremiumPlusLifetime")); - childSetVisible("badge_layout", true); - childSetVisible("partner_spacer_layout", false); - } - else - { - childSetVisible("badge_layout", false); - childSetVisible("partner_spacer_layout", true); - } -} - -void LLPanelProfileSecondLife::fillRightsData() -{ - if (getSelfProfile()) - { - return; - } - - const LLRelationship* relation = LLAvatarTracker::instance().getBuddyInfo(getAvatarId()); - // If true - we are viewing friend's profile, enable check boxes and set values. - if (relation) - { - S32 rights = relation->getRightsGrantedTo(); - bool can_see_online = LLRelationship::GRANT_ONLINE_STATUS & rights; - bool can_see_on_map = LLRelationship::GRANT_MAP_LOCATION & rights; - bool can_edit_objects = LLRelationship::GRANT_MODIFY_OBJECTS & rights; - - mCanSeeOnlineIcon->setVisible(can_see_online); - mCantSeeOnlineIcon->setVisible(!can_see_online); - mCanSeeOnMapIcon->setVisible(can_see_on_map); - mCantSeeOnMapIcon->setVisible(!can_see_on_map); - mCanEditObjectsIcon->setVisible(can_edit_objects); - mCantEditObjectsIcon->setVisible(!can_edit_objects); - - mCanSeeOnlineIcon->setEnabled(true); - mCantSeeOnlineIcon->setEnabled(true); - mCanSeeOnMapIcon->setEnabled(true); - mCantSeeOnMapIcon->setEnabled(true); - mCanEditObjectsIcon->setEnabled(true); - mCantEditObjectsIcon->setEnabled(true); - } - else - { - mCanSeeOnlineIcon->setVisible(false); - mCantSeeOnlineIcon->setVisible(false); - mCanSeeOnMapIcon->setVisible(false); - mCantSeeOnMapIcon->setVisible(false); - mCanEditObjectsIcon->setVisible(false); - mCantEditObjectsIcon->setVisible(false); - } -} - -void LLPanelProfileSecondLife::fillAgeData(const LLAvatarData* avatar_data) -{ - // Date from server comes already converted to stl timezone, - // so display it as an UTC + 0 - bool hide_age = avatar_data->hide_age && !getSelfProfile(); - std::string name_and_date = getString(hide_age ? "date_format_short" : "date_format_full"); - LLSD args_name; - args_name["datetime"] = (S32)avatar_data->born_on.secondsSinceEpoch(); - LLStringUtil::format(name_and_date, args_name); - getChild("sl_birth_date")->setValue(name_and_date); - - LLUICtrl* userAgeCtrl = getChild("user_age"); - if (hide_age) - { - userAgeCtrl->setVisible(false); - } - else - { - std::string register_date = getString("age_format"); - LLSD args_age; - args_age["[AGE]"] = LLDateUtil::ageFromDate(avatar_data->born_on, LLDate::now()); - LLStringUtil::format(register_date, args_age); - userAgeCtrl->setValue(register_date); - } - - bool showHideAgeCombo = false; - if (getSelfProfile()) - { - if (LLAvatarPropertiesProcessor::getInstance()->isHideAgeSupportedByServer()) - { - F64 birth = avatar_data->born_on.secondsSinceEpoch(); - F64 now = LLDate::now().secondsSinceEpoch(); - if (now - birth > 365 * 24 * 60 * 60) - { - mHideAge = avatar_data->hide_age; - mHideAgeCombo->setValue(mHideAge); - showHideAgeCombo = true; - } - } - } - mHideAgeCombo->setVisible(showHideAgeCombo); -} - -void LLPanelProfileSecondLife::onImageLoaded(bool success, LLViewerFetchedTexture *imagep) -{ - LLRect imageRect = mSecondLifePicLayout->getRect(); - if (!success || imagep->getFullWidth() == imagep->getFullHeight()) - { - mSecondLifePicLayout->reshape(imageRect.getWidth(), imageRect.getWidth()); - } - else - { - // assume 3:4, for sake of firestorm - mSecondLifePicLayout->reshape(imageRect.getWidth(), imageRect.getWidth() * 3 / 4); - } -} - -// virtual, called by LLAvatarTracker -void LLPanelProfileSecondLife::changed(U32 mask) -{ - updateOnlineStatus(); - if (mask != LLFriendObserver::ONLINE) - { - fillRightsData(); - } -} - -// virtual, called by LLVoiceClient -void LLPanelProfileSecondLife::onChange(EStatusType status, const std::string &channelURI, bool proximal) -{ - if(status == STATUS_JOINING || status == STATUS_LEFT_CHANNEL) - { - return; - } - - mVoiceStatus = LLAvatarActions::canCall() && (LLAvatarActions::isFriend(getAvatarId()) ? LLAvatarTracker::instance().isBuddyOnline(getAvatarId()) : true); -} - -void LLPanelProfileSecondLife::setAvatarId(const LLUUID& avatar_id) -{ - if (avatar_id.notNull()) - { - if (getAvatarId().notNull()) - { - LLAvatarTracker::instance().removeParticularFriendObserver(getAvatarId(), this); - } - - LLPanelProfilePropertiesProcessorTab::setAvatarId(avatar_id); - - if (LLAvatarActions::isFriend(getAvatarId())) - { - LLAvatarTracker::instance().addParticularFriendObserver(getAvatarId(), this); - } - } -} - -// method was disabled according to EXT-2022. Re-enabled & improved according to EXT-3880 -void LLPanelProfileSecondLife::updateOnlineStatus() -{ - const LLRelationship* relationship = LLAvatarTracker::instance().getBuddyInfo(getAvatarId()); - if (relationship != NULL) - { - // For friend let check if he allowed me to see his status - bool online = relationship->isOnline(); - bool perm_granted = relationship->isRightGrantedFrom(LLRelationship::GRANT_ONLINE_STATUS); - processOnlineStatus(true, perm_granted, online); - } - else - { - childSetVisible("friend_layout", false); - childSetVisible("online_layout", false); - childSetVisible("offline_layout", false); - } -} - -void LLPanelProfileSecondLife::processOnlineStatus(bool is_friend, bool show_online, bool online) -{ - childSetVisible("friend_layout", is_friend); - childSetVisible("online_layout", online && show_online); - childSetVisible("offline_layout", !online && show_online); -} - -void LLPanelProfileSecondLife::setLoaded() -{ - LLPanelProfileTab::setLoaded(); - - if (getSelfProfile()) - { - mShowInSearchCombo->setEnabled(true); - if (mHideAgeCombo->getVisible()) - { - mHideAgeCombo->setEnabled(true); - } - mDescriptionEdit->setEnabled(true); - } -} - - -class LLProfileImagePicker : public LLFilePickerThread -{ -public: - LLProfileImagePicker(EProfileImageType type, LLHandle *handle); - ~LLProfileImagePicker(); - void notify(const std::vector& filenames) override; - -private: - LLHandle *mHandle; - EProfileImageType mType; -}; - -LLProfileImagePicker::LLProfileImagePicker(EProfileImageType type, LLHandle *handle) - : LLFilePickerThread(LLFilePicker::FFLOAD_IMAGE), - mHandle(handle), - mType(type) -{ -} - -LLProfileImagePicker::~LLProfileImagePicker() -{ - delete mHandle; -} - -void LLProfileImagePicker::notify(const std::vector& filenames) -{ - if (mHandle->isDead()) - { - return; - } - if (filenames.empty()) - { - return; - } - std::string file_path = filenames[0]; - if (file_path.empty()) - { - return; - } - - // generate a temp texture file for coroutine - std::string temp_file = gDirUtilp->getTempFilename(); - U32 codec = LLImageBase::getCodecFromExtension(gDirUtilp->getExtension(file_path)); - const S32 MAX_DIM = 256; - if (!LLViewerTextureList::createUploadFile(file_path, temp_file, codec, MAX_DIM)) - { - LLSD notif_args; - notif_args["REASON"] = LLImage::getLastThreadError().c_str(); - LLNotificationsUtil::add("CannotUploadTexture", notif_args); - LL_WARNS("AvatarProperties") << "Failed to upload profile image of type " << (S32)mType << ", " << notif_args["REASON"].asString() << LL_ENDL; - return; - } - - std::string cap_url = gAgent.getRegionCapability(PROFILE_IMAGE_UPLOAD_CAP); - if (cap_url.empty()) - { - LLSD args; - args["CAPABILITY"] = PROFILE_IMAGE_UPLOAD_CAP; - LLNotificationsUtil::add("RegionCapabilityRequestError", args); - LL_WARNS("AvatarProperties") << "Failed to upload profile image of type " << (S32)mType << ", no cap found" << LL_ENDL; - return; - } - - switch (mType) - { - case PROFILE_IMAGE_SL: - { - LLPanelProfileSecondLife* panel = static_cast(mHandle->get()); - panel->setProfileImageUploading(true); - } - break; - case PROFILE_IMAGE_FL: - { - LLPanelProfileFirstLife* panel = static_cast(mHandle->get()); - panel->setProfileImageUploading(true); - } - break; - } - - 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) -{ - const std::string item_name = userdata.asString(); - const LLUUID agent_id = getAvatarId(); - // todo: consider moving this into LLAvatarActions::onCommit(name, id) - // and making all other flaoters, like people menu do the same - if (item_name == "im") - { - LLAvatarActions::startIM(agent_id); - } - else if (item_name == "offer_teleport") - { - LLAvatarActions::offerTeleport(agent_id); - } - else if (item_name == "request_teleport") - { - LLAvatarActions::teleportRequest(agent_id); - } - else if (item_name == "voice_call") - { - LLAvatarActions::startCall(agent_id); - } - else if (item_name == "chat_history") - { - LLAvatarActions::viewChatHistory(agent_id); - } - else if (item_name == "add_friend") - { - LLAvatarActions::requestFriendshipDialog(agent_id); - } - else if (item_name == "remove_friend") - { - LLAvatarActions::removeFriendDialog(agent_id); - } - else if (item_name == "invite_to_group") - { - LLAvatarActions::inviteToGroup(agent_id); - } - else if (item_name == "can_show_on_map") - { - LLAvatarActions::showOnMap(agent_id); - } - else if (item_name == "share") - { - LLAvatarActions::share(agent_id); - } - else if (item_name == "pay") - { - LLAvatarActions::pay(agent_id); - } - else if (item_name == "toggle_block_agent") - { - 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 == "agent_permissions") - { - onShowAgentPermissionsDialog(); - } - 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") - { - std::string url = "https://[GRID]/my/account/partners.php"; - LLSD subs; - url = LLWeb::expandURLSubstitutions(url, subs); - LLUrlAction::openURL(url); - } - else if (item_name == "upload_photo") - { - (new LLProfileImagePicker(PROFILE_IMAGE_SL, new LLHandle(LLPanel::getHandle())))->getFile(); - - LLFloater* floaterp = mFloaterTexturePickerHandle.get(); - if (floaterp) - { - floaterp->closeFloater(); - } - } - else if (item_name == "change_photo") - { - onShowTexturePicker(); - } - else if (item_name == "remove_photo") - { - onCommitProfileImage(LLUUID::null); - - LLFloater* floaterp = mFloaterTexturePickerHandle.get(); - if (floaterp) - { - floaterp->closeFloater(); - } - } -} - -bool LLPanelProfileSecondLife::onEnableMenu(const LLSD& userdata) -{ - const std::string item_name = userdata.asString(); - const LLUUID agent_id = getAvatarId(); - if (item_name == "offer_teleport" || item_name == "request_teleport") - { - return LLAvatarActions::canOfferTeleport(agent_id); - } - else if (item_name == "voice_call") - { - return mVoiceStatus; - } - else if (item_name == "chat_history") - { - return LLLogChat::isTranscriptExist(agent_id); - } - else if (item_name == "add_friend") - { - return !LLAvatarActions::isFriend(agent_id); - } - else if (item_name == "remove_friend") - { - return LLAvatarActions::isFriend(agent_id); - } - else if (item_name == "can_show_on_map") - { - return (LLAvatarTracker::instance().isBuddyOnline(agent_id) && is_agent_mappable(agent_id)) - || gAgent.isGodlike(); - } - else if (item_name == "toggle_block_agent") - { - return LLAvatarActions::canBlock(agent_id); - } - else if (item_name == "agent_permissions") - { - return LLAvatarActions::isFriend(agent_id); - } - else if (item_name == "copy_display_name" - || item_name == "copy_username") - { - return !mAvatarNameCacheConnection.connected(); - } - else if (item_name == "upload_photo" - || item_name == "change_photo") - { - std::string cap_url = gAgent.getRegionCapability(PROFILE_IMAGE_UPLOAD_CAP); - return !cap_url.empty() && !mWaitingForImageUpload && getIsLoaded(); - } - else if (item_name == "remove_photo") - { - std::string cap_url = gAgent.getRegionCapability(PROFILE_PROPERTIES_CAP); - return mSecondLifePic->getImageAssetId().notNull() && !cap_url.empty() && !mWaitingForImageUpload && getIsLoaded(); - } - - return false; -} - -bool LLPanelProfileSecondLife::onCheckMenu(const LLSD& userdata) -{ - const std::string item_name = userdata.asString(); - const LLUUID agent_id = getAvatarId(); - if (item_name == "toggle_block_agent") - { - return LLAvatarActions::isBlocked(agent_id); - } - return false; -} - -void LLPanelProfileSecondLife::onAvatarNameCacheSetName(const LLUUID& agent_id, const LLAvatarName& av_name) -{ - if (av_name.getDisplayName().empty()) - { - // something is wrong, tell user to try again later - LLNotificationsUtil::add("SetDisplayNameFailedGeneric"); - return; - } - - LL_INFOS("LegacyProfile") << "name-change now " << LLDate::now() << " next_update " - << LLDate(av_name.mNextUpdate) << LL_ENDL; - F64 now_secs = LLDate::now().secondsSinceEpoch(); - - if (now_secs < av_name.mNextUpdate) - { - // if the update time is more than a year in the future, it means updates have been blocked - // show a more general message - static const S32 YEAR = 60*60*24*365; - if (now_secs + YEAR < av_name.mNextUpdate) - { - LLNotificationsUtil::add("SetDisplayNameBlocked"); - return; - } - } - - LLFloaterReg::showInstance("display_name"); -} - -void LLPanelProfileSecondLife::setDescriptionText(const std::string &text) -{ - mSaveDescriptionChanges->setEnabled(false); - mDiscardDescriptionChanges->setEnabled(false); - mHasUnsavedDescriptionChanges = false; - - mDescriptionText = text; - mDescriptionEdit->setValue(mDescriptionText); -} - -void LLPanelProfileSecondLife::onSetDescriptionDirty() -{ - mSaveDescriptionChanges->setEnabled(true); - mDiscardDescriptionChanges->setEnabled(true); - mHasUnsavedDescriptionChanges = true; -} - -void LLPanelProfileSecondLife::onShowInSearchCallback() -{ - bool value = mShowInSearchCombo->getValue().asInteger(); - if (value == mAllowPublish) - return; - - mAllowPublish = value; - saveAgentUserInfoCoro("allow_publish", value); -} - -void LLPanelProfileSecondLife::onHideAgeCallback() -{ - bool value = mHideAgeCombo->getValue().asInteger(); - if (value == mHideAge) - return; - - mHideAge = value; - saveAgentUserInfoCoro("hide_age", value); -} - -void LLPanelProfileSecondLife::onSaveDescriptionChanges() -{ - mDescriptionText = mDescriptionEdit->getValue().asString(); - saveAgentUserInfoCoro("sl_about_text", mDescriptionText); - - mSaveDescriptionChanges->setEnabled(false); - mDiscardDescriptionChanges->setEnabled(false); - mHasUnsavedDescriptionChanges = false; -} - -void LLPanelProfileSecondLife::onDiscardDescriptionChanges() -{ - setDescriptionText(mDescriptionText); -} - -void LLPanelProfileSecondLife::onShowAgentPermissionsDialog() -{ - LLFloater *floater = mFloaterPermissionsHandle.get(); - if (!floater) - { - LLFloater* parent_floater = gFloaterView->getParentFloater(this); - if (parent_floater) - { - LLFloaterProfilePermissions * perms = new LLFloaterProfilePermissions(parent_floater, getAvatarId()); - mFloaterPermissionsHandle = perms->getHandle(); - perms->openFloater(); - perms->setVisibleAndFrontmost(true); - - parent_floater->addDependentFloater(mFloaterPermissionsHandle); - } - } - else // already open - { - floater->setMinimized(false); - floater->setVisibleAndFrontmost(true); - } -} - -void LLPanelProfileSecondLife::onShowAgentProfileTexture() -{ - if (!getIsLoaded()) - { - return; - } - - LLFloater *floater = mFloaterProfileTextureHandle.get(); - if (!floater) - { - LLFloater* parent_floater = gFloaterView->getParentFloater(this); - if (parent_floater) - { - LLFloaterProfileTexture * texture_view = new LLFloaterProfileTexture(parent_floater); - mFloaterProfileTextureHandle = texture_view->getHandle(); - if (mSecondLifePic->getImageAssetId().notNull()) - { - texture_view->loadAsset(mSecondLifePic->getImageAssetId()); - } - else - { - texture_view->resetAsset(); - } - texture_view->openFloater(); - texture_view->setVisibleAndFrontmost(true); - - parent_floater->addDependentFloater(mFloaterProfileTextureHandle); - } - } - else // already open - { - LLFloaterProfileTexture * texture_view = dynamic_cast(floater); - texture_view->setMinimized(false); - texture_view->setVisibleAndFrontmost(true); - if (mSecondLifePic->getImageAssetId().notNull()) - { - texture_view->loadAsset(mSecondLifePic->getImageAssetId()); - } - else - { - texture_view->resetAsset(); - } - } -} - -void LLPanelProfileSecondLife::onShowTexturePicker() -{ - LLFloater* floaterp = mFloaterTexturePickerHandle.get(); - - // Show the dialog - if (!floaterp) - { - LLFloater* parent_floater = gFloaterView->getParentFloater(this); - if (parent_floater) - { - // because inventory construction is somewhat slow - getWindow()->setCursor(UI_CURSOR_WAIT); - LLFloaterTexturePicker* texture_floaterp = new LLFloaterTexturePicker( - this, - mSecondLifePic->getImageAssetId(), - LLUUID::null, - mSecondLifePic->getImageAssetId(), - false, - false, - "SELECT PHOTO", - PERM_NONE, - PERM_NONE, - false, - NULL, - PICK_TEXTURE); - - mFloaterTexturePickerHandle = texture_floaterp->getHandle(); - - texture_floaterp->setOnFloaterCommitCallback([this](LLTextureCtrl::ETexturePickOp op, LLPickerSource source, const LLUUID& asset_id, const LLUUID&, const LLUUID&) - { - if (op == LLTextureCtrl::TEXTURE_SELECT) - { - onCommitProfileImage(asset_id); - } - }); - texture_floaterp->setLocalTextureEnabled(false); - texture_floaterp->setBakeTextureEnabled(false); - texture_floaterp->setCanApply(false, true, false); - - parent_floater->addDependentFloater(mFloaterTexturePickerHandle); - - texture_floaterp->openFloater(); - texture_floaterp->setFocus(true); - } - } - else - { - floaterp->setMinimized(false); - floaterp->setVisibleAndFrontmost(true); - } -} - -void LLPanelProfileSecondLife::onCommitProfileImage(const LLUUID& id) -{ - if (mSecondLifePic->getImageAssetId() == id) - return; - - std::function callback = [id](bool result) - { - if (result) - { - LLAvatarIconIDCache::getInstance()->add(gAgentID, id); - // Should trigger callbacks in icon controls (or request Legacy) - LLAvatarPropertiesProcessor::getInstance()->sendAvatarPropertiesRequest(gAgentID); - } - }; - - if (!saveAgentUserInfoCoro("sl_image_id", id, callback)) - return; - - mSecondLifePic->setValue(id); - - LLFloater *floater = mFloaterProfileTextureHandle.get(); - if (floater) - { - LLFloaterProfileTexture * texture_view = dynamic_cast(floater); - if (id == LLUUID::null) - { - texture_view->resetAsset(); - } - else - { - texture_view->loadAsset(id); - } - } -} - -////////////////////////////////////////////////////////////////////////// -// LLPanelProfileWeb - -LLPanelProfileWeb::LLPanelProfileWeb() - : LLPanelProfileTab() - , mWebBrowser(NULL) - , mAvatarNameCacheConnection() -{ -} - -LLPanelProfileWeb::~LLPanelProfileWeb() -{ - if (mAvatarNameCacheConnection.connected()) - { - mAvatarNameCacheConnection.disconnect(); - } -} - -void LLPanelProfileWeb::onOpen(const LLSD& key) -{ - LLPanelProfileTab::onOpen(key); - - resetData(); - - mAvatarNameCacheConnection = LLAvatarNameCache::get(getAvatarId(), boost::bind(&LLPanelProfileWeb::onAvatarNameCache, this, _1, _2)); -} - -bool LLPanelProfileWeb::postBuild() -{ - mWebBrowser = getChild("profile_html"); - mWebBrowser->addObserver(this); - mWebBrowser->setHomePageUrl("about:blank"); - - return true; -} - -void LLPanelProfileWeb::resetData() -{ - mWebBrowser->navigateHome(); -} - -void LLPanelProfileWeb::updateData() -{ - LLUUID avatar_id = getAvatarId(); - if (!getStarted() && avatar_id.notNull() && !mURLWebProfile.empty()) - { - setIsLoading(); - - mWebBrowser->setVisible(true); - mPerformanceTimer.start(); - mWebBrowser->navigateTo(mURLWebProfile, HTTP_CONTENT_TEXT_HTML); - } -} - -void LLPanelProfileWeb::onAvatarNameCache(const LLUUID& agent_id, const LLAvatarName& av_name) -{ - mAvatarNameCacheConnection.disconnect(); - - std::string username = av_name.getAccountName(); - if (username.empty()) - { - username = LLCacheName::buildUsername(av_name.getDisplayName()); - } - else - { - LLStringUtil::replaceChar(username, ' ', '.'); - } - - mURLWebProfile = getProfileURL(username, true); - if (mURLWebProfile.empty()) - { - return; - } - - //if the tab was opened before name was resolved, load the panel now - updateData(); -} - -void LLPanelProfileWeb::onCommitLoad(LLUICtrl* ctrl) -{ - if (!mURLHome.empty()) - { - LLSD::String valstr = ctrl->getValue().asString(); - if (valstr.empty()) - { - mWebBrowser->setVisible(true); - mPerformanceTimer.start(); - mWebBrowser->navigateTo( mURLHome, HTTP_CONTENT_TEXT_HTML ); - } - else if (valstr == "popout") - { - // open in viewer's browser, new window - LLWeb::loadURLInternal(mURLHome); - } - else if (valstr == "external") - { - // open in external browser - LLWeb::loadURLExternal(mURLHome); - } - } -} - -void LLPanelProfileWeb::handleMediaEvent(LLPluginClassMedia* self, EMediaEvent event) -{ - switch(event) - { - case MEDIA_EVENT_STATUS_TEXT_CHANGED: - childSetValue("status_text", LLSD( self->getStatusText() ) ); - break; - - case MEDIA_EVENT_NAVIGATE_BEGIN: - { - if (mFirstNavigate) - { - mFirstNavigate = false; - } - else - { - mPerformanceTimer.start(); - } - } - break; - - case MEDIA_EVENT_NAVIGATE_COMPLETE: - { - LLStringUtil::format_map_t args; - args["[TIME]"] = llformat("%.2f", mPerformanceTimer.getElapsedTimeF32()); - childSetValue("status_text", LLSD( getString("LoadTime", args)) ); - - setLoaded(); - } - break; - - default: - // Having a default case makes the compiler happy. - break; - } -} - - -////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////// - -LLPanelProfileFirstLife::LLPanelProfileFirstLife() - : LLPanelProfilePropertiesProcessorTab() - , mHasUnsavedChanges(false) -{ -} - -LLPanelProfileFirstLife::~LLPanelProfileFirstLife() -{ -} - -bool LLPanelProfileFirstLife::postBuild() -{ - mDescriptionEdit = getChild("fl_description_edit"); - mPicture = getChild("real_world_pic"); - - mUploadPhoto = getChild("fl_upload_image"); - mChangePhoto = getChild("fl_change_image"); - mRemovePhoto = getChild("fl_remove_image"); - mSaveChanges = getChild("fl_save_changes"); - mDiscardChanges = getChild("fl_discard_changes"); - - mUploadPhoto->setCommitCallback([this](LLUICtrl*, void*) { onUploadPhoto(); }, nullptr); - mChangePhoto->setCommitCallback([this](LLUICtrl*, void*) { onChangePhoto(); }, nullptr); - mRemovePhoto->setCommitCallback([this](LLUICtrl*, void*) { onRemovePhoto(); }, nullptr); - mSaveChanges->setCommitCallback([this](LLUICtrl*, void*) { onSaveDescriptionChanges(); }, nullptr); - mDiscardChanges->setCommitCallback([this](LLUICtrl*, void*) { onDiscardDescriptionChanges(); }, nullptr); - mDescriptionEdit->setKeystrokeCallback([this](LLTextEditor* caller) { onSetDescriptionDirty(); }); - - return true; -} - -void LLPanelProfileFirstLife::onOpen(const LLSD& key) -{ - LLPanelProfileTab::onOpen(key); - - if (!getSelfProfile()) - { - // Otherwise as the only focusable element it will be selected - mDescriptionEdit->setTabStop(false); - } - - resetData(); -} - -void LLPanelProfileFirstLife::setProfileImageUploading(bool loading) -{ - mUploadPhoto->setEnabled(!loading); - mChangePhoto->setEnabled(!loading); - mRemovePhoto->setEnabled(!loading && mPicture->getImageAssetId().notNull()); - - LLLoadingIndicator* indicator = getChild("image_upload_indicator"); - indicator->setVisible(loading); - if (loading) - { - indicator->start(); - } - else - { - indicator->stop(); - } -} - -void LLPanelProfileFirstLife::setProfileImageUploaded(const LLUUID &image_asset_id) -{ - mPicture->setValue(image_asset_id); - setProfileImageUploading(false); -} - -void LLPanelProfileFirstLife::commitUnsavedChanges() -{ - if (mHasUnsavedChanges) - { - onSaveDescriptionChanges(); - } -} - -void LLPanelProfileFirstLife::onUploadPhoto() -{ - (new LLProfileImagePicker(PROFILE_IMAGE_FL, new LLHandle(LLPanel::getHandle())))->getFile(); - - LLFloater* floaterp = mFloaterTexturePickerHandle.get(); - if (floaterp) - { - floaterp->closeFloater(); - } -} - -void LLPanelProfileFirstLife::onChangePhoto() -{ - LLFloater* floaterp = mFloaterTexturePickerHandle.get(); - - // Show the dialog - if (!floaterp) - { - LLFloater* parent_floater = gFloaterView->getParentFloater(this); - if (parent_floater) - { - // because inventory construction is somewhat slow - getWindow()->setCursor(UI_CURSOR_WAIT); - LLFloaterTexturePicker* texture_floaterp = new LLFloaterTexturePicker( - this, - mPicture->getImageAssetId(), - LLUUID::null, - mPicture->getImageAssetId(), - false, - false, - "SELECT PHOTO", - PERM_NONE, - PERM_NONE, - false, - NULL, - PICK_TEXTURE); - - mFloaterTexturePickerHandle = texture_floaterp->getHandle(); - - texture_floaterp->setOnFloaterCommitCallback([this](LLTextureCtrl::ETexturePickOp op, LLPickerSource source, const LLUUID& asset_id, const LLUUID&, const LLUUID&) - { - if (op == LLTextureCtrl::TEXTURE_SELECT) - { - onCommitPhoto(asset_id); - } - }); - texture_floaterp->setLocalTextureEnabled(false); - texture_floaterp->setCanApply(false, true, false); - - parent_floater->addDependentFloater(mFloaterTexturePickerHandle); - - texture_floaterp->openFloater(); - texture_floaterp->setFocus(true); - } - } - else - { - floaterp->setMinimized(false); - floaterp->setVisibleAndFrontmost(true); - } -} - -void LLPanelProfileFirstLife::onRemovePhoto() -{ - onCommitPhoto(LLUUID::null); - - LLFloater* floaterp = mFloaterTexturePickerHandle.get(); - if (floaterp) - { - floaterp->closeFloater(); - } -} - -void LLPanelProfileFirstLife::onCommitPhoto(const LLUUID& id) -{ - if (mPicture->getImageAssetId() == id) - return; - - if (!saveAgentUserInfoCoro("fl_image_id", id)) - return; - - mPicture->setValue(id); - - mRemovePhoto->setEnabled(id.notNull()); -} - -void LLPanelProfileFirstLife::setDescriptionText(const std::string &text) -{ - mSaveChanges->setEnabled(false); - mDiscardChanges->setEnabled(false); - mHasUnsavedChanges = false; - - mCurrentDescription = text; - mDescriptionEdit->setValue(mCurrentDescription); -} - -void LLPanelProfileFirstLife::onSetDescriptionDirty() -{ - mSaveChanges->setEnabled(true); - mDiscardChanges->setEnabled(true); - mHasUnsavedChanges = true; -} - -void LLPanelProfileFirstLife::onSaveDescriptionChanges() -{ - mCurrentDescription = mDescriptionEdit->getValue().asString(); - saveAgentUserInfoCoro("fl_about_text", mCurrentDescription); - - mSaveChanges->setEnabled(false); - mDiscardChanges->setEnabled(false); - mHasUnsavedChanges = false; -} - -void LLPanelProfileFirstLife::onDiscardDescriptionChanges() -{ - setDescriptionText(mCurrentDescription); -} - -void LLPanelProfileFirstLife::processProperties(void* data, EAvatarProcessorType type) -{ - if (APT_PROPERTIES == type) - { - LLAvatarData* avatar_data = static_cast(data); - if (avatar_data && getAvatarId() == avatar_data->avatar_id) - { - processProperties(avatar_data); - } - } -} - -void LLPanelProfileFirstLife::processProperties(const LLAvatarData* avatar_data) -{ - setDescriptionText(avatar_data->fl_about_text); - - mPicture->setValue(avatar_data->fl_image_id); - - setLoaded(); -} - -void LLPanelProfileFirstLife::resetData() -{ - setDescriptionText(std::string()); - mPicture->setValue(LLUUID::null); - - mUploadPhoto->setVisible(getSelfProfile()); - mChangePhoto->setVisible(getSelfProfile()); - mRemovePhoto->setVisible(getSelfProfile()); - mSaveChanges->setVisible(getSelfProfile()); - mDiscardChanges->setVisible(getSelfProfile()); -} - -void LLPanelProfileFirstLife::setLoaded() -{ - LLPanelProfileTab::setLoaded(); - - if (getSelfProfile()) - { - mDescriptionEdit->setEnabled(true); - mPicture->setEnabled(true); - mRemovePhoto->setEnabled(mPicture->getImageAssetId().notNull()); - } -} - -////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////// - -LLPanelProfileNotes::LLPanelProfileNotes() -: LLPanelProfilePropertiesProcessorTab() - , mHasUnsavedChanges(false) -{ - -} - -LLPanelProfileNotes::~LLPanelProfileNotes() -{ -} - -void LLPanelProfileNotes::commitUnsavedChanges() -{ - if (mHasUnsavedChanges) - { - onSaveNotesChanges(); - } -} - -bool LLPanelProfileNotes::postBuild() -{ - mNotesEditor = getChild("notes_edit"); - mSaveChanges = getChild("notes_save_changes"); - mDiscardChanges = getChild("notes_discard_changes"); - - mSaveChanges->setCommitCallback([this](LLUICtrl*, void*) { onSaveNotesChanges(); }, nullptr); - mDiscardChanges->setCommitCallback([this](LLUICtrl*, void*) { onDiscardNotesChanges(); }, nullptr); - mNotesEditor->setKeystrokeCallback([this](LLTextEditor* caller) { onSetNotesDirty(); }); - - return true; -} - -void LLPanelProfileNotes::onOpen(const LLSD& key) -{ - LLPanelProfileTab::onOpen(key); - - resetData(); -} - -void LLPanelProfileNotes::setNotesText(const std::string &text) -{ - mSaveChanges->setEnabled(false); - mDiscardChanges->setEnabled(false); - mHasUnsavedChanges = false; - - mCurrentNotes = text; - mNotesEditor->setValue(mCurrentNotes); -} - -void LLPanelProfileNotes::onSetNotesDirty() -{ - mSaveChanges->setEnabled(true); - mDiscardChanges->setEnabled(true); - mHasUnsavedChanges = true; -} - -void LLPanelProfileNotes::onSaveNotesChanges() -{ - mCurrentNotes = mNotesEditor->getValue().asString(); - saveAgentUserInfoCoro("notes", mCurrentNotes); - - mSaveChanges->setEnabled(false); - mDiscardChanges->setEnabled(false); - mHasUnsavedChanges = false; -} - -void LLPanelProfileNotes::onDiscardNotesChanges() -{ - setNotesText(mCurrentNotes); -} - -void LLPanelProfileNotes::processProperties(void* data, EAvatarProcessorType type) -{ - if (APT_PROPERTIES == type) - { - LLAvatarData* avatar_data = static_cast(data); - if (avatar_data && getAvatarId() == avatar_data->avatar_id) - { - processProperties(avatar_data); - } - } -} - -void LLPanelProfileNotes::processProperties(const LLAvatarData* avatar_data) -{ - setNotesText(avatar_data->notes); - mNotesEditor->setEnabled(true); - setLoaded(); -} - -void LLPanelProfileNotes::resetData() -{ - resetLoading(); - setNotesText(std::string()); -} - - -////////////////////////////////////////////////////////////////////////// -// LLPanelProfile - -LLPanelProfile::LLPanelProfile() - : LLPanelProfileTab() -{ -} - -LLPanelProfile::~LLPanelProfile() -{ -} - -bool LLPanelProfile::postBuild() -{ - return true; -} - -void LLPanelProfile::onTabChange() -{ - LLPanelProfileTab* active_panel = dynamic_cast(mTabContainer->getCurrentPanel()); - if (active_panel) - { - active_panel->updateData(); - } -} - -void LLPanelProfile::onOpen(const LLSD& key) -{ - LLUUID avatar_id = key["id"].asUUID(); - - // Don't reload the same profile - if (getAvatarId() == avatar_id) - { - return; - } - - LLPanelProfileTab::onOpen(avatar_id); - - mTabContainer = getChild("panel_profile_tabs"); - mPanelSecondlife = findChild(PANEL_SECONDLIFE); - mPanelWeb = findChild(PANEL_WEB); - mPanelPicks = findChild(PANEL_PICKS); - mPanelClassifieds = findChild(PANEL_CLASSIFIEDS); - mPanelFirstlife = findChild(PANEL_FIRSTLIFE); - mPanelNotes = findChild(PANEL_NOTES); - - mPanelSecondlife->onOpen(avatar_id); - mPanelWeb->onOpen(avatar_id); - mPanelPicks->onOpen(avatar_id); - mPanelClassifieds->onOpen(avatar_id); - mPanelFirstlife->onOpen(avatar_id); - mPanelNotes->onOpen(avatar_id); - - // Always request the base profile info - resetLoading(); - updateData(); - - // Some tabs only request data when opened - mTabContainer->setCommitCallback(boost::bind(&LLPanelProfile::onTabChange, this)); -} - -void LLPanelProfile::updateData() -{ - LLUUID avatar_id = getAvatarId(); - // Todo: getIsloading functionality needs to be expanded to - // include 'inited' or 'data_provided' state to not rerequest - if (!getStarted() && avatar_id.notNull()) - { - setIsLoading(); - - mPanelSecondlife->setIsLoading(); - mPanelPicks->setIsLoading(); - mPanelFirstlife->setIsLoading(); - mPanelNotes->setIsLoading(); - - LLAvatarPropertiesProcessor::getInstance()->sendAvatarPropertiesRequest(getAvatarId()); - } -} - -void LLPanelProfile::refreshName() -{ - mPanelSecondlife->refreshName(); -} - -void LLPanelProfile::createPick(const LLPickData &data) -{ - mTabContainer->selectTabPanel(mPanelPicks); - mPanelPicks->createPick(data); -} - -void LLPanelProfile::showPick(const LLUUID& pick_id) -{ - if (pick_id.notNull()) - { - mPanelPicks->selectPick(pick_id); - } - mTabContainer->selectTabPanel(mPanelPicks); -} - -bool LLPanelProfile::isPickTabSelected() -{ - return (mTabContainer->getCurrentPanel() == mPanelPicks); -} - -bool LLPanelProfile::isNotesTabSelected() -{ - return (mTabContainer->getCurrentPanel() == mPanelNotes); -} - -bool LLPanelProfile::hasUnsavedChanges() -{ - return mPanelSecondlife->hasUnsavedChanges() - || mPanelPicks->hasUnsavedChanges() - || mPanelClassifieds->hasUnsavedChanges() - || mPanelFirstlife->hasUnsavedChanges() - || mPanelNotes->hasUnsavedChanges(); -} - -bool LLPanelProfile::hasUnpublishedClassifieds() -{ - return mPanelClassifieds->hasNewClassifieds(); -} - -void LLPanelProfile::commitUnsavedChanges() -{ - mPanelSecondlife->commitUnsavedChanges(); - mPanelPicks->commitUnsavedChanges(); - mPanelClassifieds->commitUnsavedChanges(); - mPanelFirstlife->commitUnsavedChanges(); - mPanelNotes->commitUnsavedChanges(); -} - -void LLPanelProfile::showClassified(const LLUUID& classified_id, bool edit) -{ - if (classified_id.notNull()) - { - mPanelClassifieds->selectClassified(classified_id, edit); - } - mTabContainer->selectTabPanel(mPanelClassifieds); -} - -void LLPanelProfile::createClassified() -{ - mPanelClassifieds->createClassified(); - mTabContainer->selectTabPanel(mPanelClassifieds); -} - +/** +* @file llpanelprofile.cpp +* @brief Profile panel implementation +* +* $LicenseInfo:firstyear=2022&license=viewerlgpl$ +* Second Life Viewer Source Code +* Copyright (C) 2022, 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$ +*/ + +#include "llviewerprecompiledheaders.h" +#include "llpanelprofile.h" + +// Common +#include "llavatarnamecache.h" +#include "llsdutil.h" +#include "llslurl.h" +#include "lldateutil.h" //ageFromDate + +// UI +#include "llavatariconctrl.h" +#include "llclipboard.h" +#include "llcheckboxctrl.h" +#include "llcombobox.h" +#include "lllineeditor.h" +#include "llloadingindicator.h" +#include "llmenubutton.h" +#include "lltabcontainer.h" +#include "lltextbox.h" +#include "lltexteditor.h" +#include "lltexturectrl.h" +#include "lltoggleablemenu.h" +#include "lltooldraganddrop.h" +#include "llgrouplist.h" +#include "llurlaction.h" + +// Image +#include "llimagej2c.h" + +// Newview +#include "llagent.h" //gAgent +#include "llagentpicksinfo.h" +#include "llavataractions.h" +#include "llavatarpropertiesprocessor.h" +#include "llcallingcard.h" +#include "llcommandhandler.h" +#include "llfloaterprofiletexture.h" +#include "llfloaterreg.h" +#include "llfloaterreporter.h" +#include "llfilepicker.h" +#include "llfirstuse.h" +#include "llgroupactions.h" +#include "lllogchat.h" +#include "llmutelist.h" +#include "llnotificationsutil.h" +#include "llpanelblockedlist.h" +#include "llpanelprofileclassifieds.h" +#include "llpanelprofilepicks.h" +#include "lltrans.h" +#include "llviewercontrol.h" +#include "llviewermenu.h" //is_agent_mappable +#include "llviewermenufile.h" +#include "llviewertexturelist.h" +#include "llvoiceclient.h" +#include "llweb.h" + + +static LLPanelInjector t_panel_profile_secondlife("panel_profile_secondlife"); +static LLPanelInjector t_panel_web("panel_profile_web"); +static LLPanelInjector t_panel_picks("panel_profile_picks"); +static LLPanelInjector t_panel_firstlife("panel_profile_firstlife"); +static LLPanelInjector t_panel_notes("panel_profile_notes"); +static LLPanelInjector t_panel_profile("panel_profile"); + +static const std::string PANEL_SECONDLIFE = "panel_profile_secondlife"; +static const std::string PANEL_WEB = "panel_profile_web"; +static const std::string PANEL_PICKS = "panel_profile_picks"; +static const std::string PANEL_CLASSIFIEDS = "panel_profile_classifieds"; +static const std::string PANEL_FIRSTLIFE = "panel_profile_firstlife"; +static const std::string PANEL_NOTES = "panel_profile_notes"; +static const std::string PANEL_PROFILE_VIEW = "panel_profile_view"; + +static const std::string PROFILE_PROPERTIES_CAP = "AgentProfile"; +static const std::string PROFILE_IMAGE_UPLOAD_CAP = "UploadAgentProfileImage"; + + +////////////////////////////////////////////////////////////////////////// + +LLUUID post_profile_image(std::string cap_url, const LLSD &first_data, std::string path_to_image, LLHandle *handle) +{ + LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID); + LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t + httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("post_profile_image_coro", httpPolicy)); + LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest); + LLCore::HttpHeaders::ptr_t httpHeaders; + + LLCore::HttpOptions::ptr_t httpOpts(new LLCore::HttpOptions); + httpOpts->setFollowRedirects(true); + + LLSD result = httpAdapter->postAndSuspend(httpRequest, cap_url, first_data, httpOpts, httpHeaders); + + LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS]; + LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults); + + if (!status) + { + // todo: notification? + LL_WARNS("AvatarProperties") << "Failed to get uploader cap " << status.toString() << LL_ENDL; + return LLUUID::null; + } + if (!result.has("uploader")) + { + // todo: notification? + LL_WARNS("AvatarProperties") << "Failed to get uploader cap, response contains no data." << LL_ENDL; + 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; + return LLUUID::null; + } + + // Upload the image + LLCore::HttpRequest::ptr_t uploaderhttpRequest(new LLCore::HttpRequest); + LLCore::HttpHeaders::ptr_t uploaderhttpHeaders(new LLCore::HttpHeaders); + LLCore::HttpOptions::ptr_t uploaderhttpOpts(new LLCore::HttpOptions); + S64 length; + + { + llifstream instream(path_to_image.c_str(), std::iostream::binary | std::iostream::ate); + if (!instream.is_open()) + { + LL_WARNS("AvatarProperties") << "Failed to open file " << path_to_image << LL_ENDL; + return LLUUID::null; + } + length = instream.tellg(); + } + + uploaderhttpHeaders->append(HTTP_OUT_HEADER_CONTENT_TYPE, "application/jp2"); // optional + uploaderhttpHeaders->append(HTTP_OUT_HEADER_CONTENT_LENGTH, llformat("%d", length)); // required! + uploaderhttpOpts->setFollowRedirects(true); + + result = httpAdapter->postFileAndSuspend(uploaderhttpRequest, uploader_cap, path_to_image, uploaderhttpOpts, uploaderhttpHeaders); + + httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS]; + status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults); + + LL_DEBUGS("AvatarProperties") << result << LL_ENDL; + + if (!status) + { + LL_WARNS("AvatarProperties") << "Failed to upload image " << status.toString() << LL_ENDL; + return LLUUID::null; + } + + if (result["state"].asString() != "complete") + { + if (result.has("message")) + { + LL_WARNS("AvatarProperties") << "Failed to upload image, state " << result["state"] << " message: " << result["message"] << LL_ENDL; + } + else + { + LL_WARNS("AvatarProperties") << "Failed to upload image " << result << LL_ENDL; + } + 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 *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 + if (!handle->isDead()) + { + switch (type) + { + case PROFILE_IMAGE_SL: + { + LLPanelProfileSecondLife* panel = static_cast(handle->get()); + if (result.notNull()) + { + panel->setProfileImageUploaded(result); + } + else + { + // failure, just stop progress indicator + panel->setProfileImageUploading(false); + } + break; + } + case PROFILE_IMAGE_FL: + { + LLPanelProfileFirstLife* panel = static_cast(handle->get()); + if (result.notNull()) + { + panel->setProfileImageUploaded(result); + } + else + { + // failure, just stop progress indicator + panel->setProfileImageUploading(false); + } + break; + } + } + } + + if (type == PROFILE_IMAGE_SL && result.notNull()) + { + LLAvatarIconIDCache::getInstance()->add(gAgentID, result); + // Should trigger callbacks in icon controls + LLAvatarPropertiesProcessor::getInstance()->sendAvatarPropertiesRequest(gAgentID); + } + + // Cleanup + LLFile::remove(path_to_image); + delete handle; +} + +////////////////////////////////////////////////////////////////////////// +// LLProfileHandler + +class LLProfileHandler : public LLCommandHandler +{ +public: + // requires trusted browser to trigger + LLProfileHandler() : LLCommandHandler("profile", UNTRUSTED_THROTTLE) { } + + bool handle(const LLSD& params, + const LLSD& query_map, + const std::string& grid, + LLMediaCtrl* web) + { + if (params.size() < 1) return false; + std::string agent_name = params[0]; + LL_INFOS() << "Profile, agent_name " << agent_name << LL_ENDL; + std::string url = getProfileURL(agent_name); + LLWeb::loadURLInternal(url); + + return true; + } +}; +LLProfileHandler gProfileHandler; + + +////////////////////////////////////////////////////////////////////////// +// LLAgentHandler + +class LLAgentHandler : public LLCommandHandler +{ +public: + // requires trusted browser to trigger + LLAgentHandler() : LLCommandHandler("agent", UNTRUSTED_THROTTLE) { } + + virtual bool canHandleUntrusted( + const LLSD& params, + const LLSD& query_map, + LLMediaCtrl* web, + const std::string& nav_type) + { + if (params.size() < 2) + { + return true; // don't block, will fail later + } + + if (nav_type == NAV_TYPE_CLICKED + || nav_type == NAV_TYPE_EXTERNAL) + { + return true; + } + + const std::string verb = params[1].asString(); + if (verb == "about" || verb == "inspect" || verb == "reportAbuse") + { + return true; + } + return false; + } + + bool handle(const LLSD& params, + const LLSD& query_map, + const std::string& grid, + LLMediaCtrl* web) + { + if (params.size() < 2) return false; + LLUUID avatar_id; + if (!avatar_id.set(params[0], false)) + { + return false; + } + + const std::string verb = params[1].asString(); + if (verb == "about") + { + LLAvatarActions::showProfile(avatar_id); + return true; + } + + if (verb == "inspect") + { + LLFloaterReg::showInstance("inspect_avatar", LLSD().with("avatar_id", avatar_id)); + return true; + } + + if (verb == "im") + { + LLAvatarActions::startIM(avatar_id); + return true; + } + + if (verb == "pay") + { + if (!LLUI::getInstance()->mSettingGroups["config"]->getBOOL("EnableAvatarPay")) + { + LLNotificationsUtil::add("NoAvatarPay", LLSD(), LLSD(), std::string("SwitchToStandardSkinAndQuit")); + return true; + } + + LLAvatarActions::pay(avatar_id); + return true; + } + + if (verb == "offerteleport") + { + LLAvatarActions::offerTeleport(avatar_id); + return true; + } + + if (verb == "requestfriend") + { + LLAvatarActions::requestFriendshipDialog(avatar_id); + return true; + } + + if (verb == "removefriend") + { + LLAvatarActions::removeFriendDialog(avatar_id); + return true; + } + + if (verb == "mute") + { + if (! LLAvatarActions::isBlocked(avatar_id)) + { + LLAvatarActions::toggleBlock(avatar_id); + } + return true; + } + + if (verb == "unmute") + { + if (LLAvatarActions::isBlocked(avatar_id)) + { + LLAvatarActions::toggleBlock(avatar_id); + } + return true; + } + + if (verb == "block") + { + if (params.size() > 2) + { + const std::string object_name = LLURI::unescape(params[2].asString()); + LLMute mute(avatar_id, object_name, LLMute::OBJECT); + LLMuteList::getInstance()->add(mute); + LLPanelBlockedList::showPanelAndSelect(mute.mID); + } + return true; + } + + if (verb == "unblock") + { + if (params.size() > 2) + { + const std::string object_name = params[2].asString(); + LLMute mute(avatar_id, object_name, LLMute::OBJECT); + LLMuteList::getInstance()->remove(mute); + } + return true; + } + + // reportAbuse is here due to convoluted avatar handling + // in LLScrollListCtrl and LLTextBase + if (verb == "reportAbuse" && web == NULL) + { + LLAvatarName av_name; + if (LLAvatarNameCache::get(avatar_id, &av_name)) + { + LLFloaterReporter::showFromAvatar(avatar_id, av_name.getCompleteName()); + } + else + { + LLFloaterReporter::showFromAvatar(avatar_id, "not avaliable"); + } + return true; + } + return false; + } +}; +LLAgentHandler gAgentHandler; + + +///---------------------------------------------------------------------------- +/// LLFloaterProfilePermissions +///---------------------------------------------------------------------------- + +class LLFloaterProfilePermissions + : public LLFloater + , public LLFriendObserver +{ +public: + LLFloaterProfilePermissions(LLView * owner, const LLUUID &avatar_id); + ~LLFloaterProfilePermissions(); + bool postBuild() override; + void onOpen(const LLSD& key) override; + void draw() override; + void changed(U32 mask) override; // LLFriendObserver + + void onAvatarNameCache(const LLUUID& agent_id, const LLAvatarName& av_name); + bool hasUnsavedChanges() { return mHasUnsavedPermChanges; } + + void onApplyRights(); + +private: + void fillRightsData(); + void rightsConfirmationCallback(const LLSD& notification, const LLSD& response); + void confirmModifyRights(bool grant); + void onCommitSeeOnlineRights(); + void onCommitEditRights(); + void onCancel(); + + LLTextBase* mDescription; + LLCheckBoxCtrl* mOnlineStatus; + LLCheckBoxCtrl* mMapRights; + LLCheckBoxCtrl* mEditObjectRights; + LLButton* mOkBtn; + LLButton* mCancelBtn; + + LLUUID mAvatarID; + F32 mContextConeOpacity; + bool mHasUnsavedPermChanges; + LLHandle mOwnerHandle; + + boost::signals2::connection mAvatarNameCacheConnection; +}; + +LLFloaterProfilePermissions::LLFloaterProfilePermissions(LLView * owner, const LLUUID &avatar_id) + : LLFloater(LLSD()) + , mAvatarID(avatar_id) + , mContextConeOpacity(0.0f) + , mHasUnsavedPermChanges(false) + , mOwnerHandle(owner->getHandle()) +{ + buildFromFile("floater_profile_permissions.xml"); +} + +LLFloaterProfilePermissions::~LLFloaterProfilePermissions() +{ + mAvatarNameCacheConnection.disconnect(); + if (mAvatarID.notNull()) + { + LLAvatarTracker::instance().removeParticularFriendObserver(mAvatarID, this); + } +} + +bool LLFloaterProfilePermissions::postBuild() +{ + mDescription = getChild("perm_description"); + mOnlineStatus = getChild("online_check"); + mMapRights = getChild("map_check"); + mEditObjectRights = getChild("objects_check"); + mOkBtn = getChild("perms_btn_ok"); + mCancelBtn = getChild("perms_btn_cancel"); + + mOnlineStatus->setCommitCallback([this](LLUICtrl*, void*) { onCommitSeeOnlineRights(); }, nullptr); + mMapRights->setCommitCallback([this](LLUICtrl*, void*) { mHasUnsavedPermChanges = true; }, nullptr); + mEditObjectRights->setCommitCallback([this](LLUICtrl*, void*) { onCommitEditRights(); }, nullptr); + mOkBtn->setCommitCallback([this](LLUICtrl*, void*) { onApplyRights(); }, nullptr); + mCancelBtn->setCommitCallback([this](LLUICtrl*, void*) { onCancel(); }, nullptr); + + return true; +} + +void LLFloaterProfilePermissions::onOpen(const LLSD& key) +{ + if (LLAvatarActions::isFriend(mAvatarID)) + { + LLAvatarTracker::instance().addParticularFriendObserver(mAvatarID, this); + fillRightsData(); + } + + mCancelBtn->setFocus(true); + + mAvatarNameCacheConnection = LLAvatarNameCache::get(mAvatarID, boost::bind(&LLFloaterProfilePermissions::onAvatarNameCache, this, _1, _2)); +} + +void LLFloaterProfilePermissions::draw() +{ + // drawFrustum + LLView *owner = mOwnerHandle.get(); + static LLCachedControl max_opacity(gSavedSettings, "PickerContextOpacity", 0.4f); + drawConeToOwner(mContextConeOpacity, max_opacity, owner); + LLFloater::draw(); +} + +void LLFloaterProfilePermissions::changed(U32 mask) +{ + if (mask != LLFriendObserver::ONLINE) + { + fillRightsData(); + } +} + +void LLFloaterProfilePermissions::onAvatarNameCache(const LLUUID& agent_id, const LLAvatarName& av_name) +{ + mAvatarNameCacheConnection.disconnect(); + + LLStringUtil::format_map_t args; + args["[AGENT_NAME]"] = av_name.getDisplayName(); + std::string descritpion = getString("description_string", args); + mDescription->setValue(descritpion); +} + +void LLFloaterProfilePermissions::fillRightsData() +{ + const LLRelationship* relation = LLAvatarTracker::instance().getBuddyInfo(mAvatarID); + // If true - we are viewing friend's profile, enable check boxes and set values. + if (relation) + { + S32 rights = relation->getRightsGrantedTo(); + + bool see_online = LLRelationship::GRANT_ONLINE_STATUS & rights; + mOnlineStatus->setValue(see_online); + mMapRights->setEnabled(see_online); + mMapRights->setValue(LLRelationship::GRANT_MAP_LOCATION & rights); + mEditObjectRights->setValue(LLRelationship::GRANT_MODIFY_OBJECTS & rights); + } + else + { + closeFloater(); + LL_INFOS("ProfilePermissions") << "Floater closing since agent is no longer a friend" << LL_ENDL; + } +} + +void LLFloaterProfilePermissions::rightsConfirmationCallback(const LLSD& notification, + const LLSD& response) +{ + S32 option = LLNotificationsUtil::getSelectedOption(notification, response); + if (option != 0) // canceled + { + mEditObjectRights->setValue(!mEditObjectRights->getValue().asBoolean()); + } + else + { + mHasUnsavedPermChanges = true; + } +} + +void LLFloaterProfilePermissions::confirmModifyRights(bool grant) +{ + LLSD args; + args["NAME"] = LLSLURL("agent", mAvatarID, "completename").getSLURLString(); + LLNotificationsUtil::add(grant ? "GrantModifyRights" : "RevokeModifyRights", args, LLSD(), + boost::bind(&LLFloaterProfilePermissions::rightsConfirmationCallback, this, _1, _2)); +} + +void LLFloaterProfilePermissions::onCommitSeeOnlineRights() +{ + bool see_online = mOnlineStatus->getValue().asBoolean(); + mMapRights->setEnabled(see_online); + if (see_online) + { + const LLRelationship* relation = LLAvatarTracker::instance().getBuddyInfo(mAvatarID); + if (relation) + { + S32 rights = relation->getRightsGrantedTo(); + mMapRights->setValue(LLRelationship::GRANT_MAP_LOCATION & rights); + } + else + { + closeFloater(); + LL_INFOS("ProfilePermissions") << "Floater closing since agent is no longer a friend" << LL_ENDL; + } + } + else + { + mMapRights->setValue(false); + } + mHasUnsavedPermChanges = true; +} + +void LLFloaterProfilePermissions::onCommitEditRights() +{ + const LLRelationship* buddy_relationship = LLAvatarTracker::instance().getBuddyInfo(mAvatarID); + + if (!buddy_relationship) + { + LL_WARNS("ProfilePermissions") << "Trying to modify rights for non-friend avatar. Closing floater." << LL_ENDL; + closeFloater(); + return; + } + + bool allow_modify_objects = mEditObjectRights->getValue().asBoolean(); + + // if modify objects checkbox clicked + if (buddy_relationship->isRightGrantedTo( + LLRelationship::GRANT_MODIFY_OBJECTS) != allow_modify_objects) + { + confirmModifyRights(allow_modify_objects); + } +} + +void LLFloaterProfilePermissions::onApplyRights() +{ + const LLRelationship* buddy_relationship = LLAvatarTracker::instance().getBuddyInfo(mAvatarID); + + if (!buddy_relationship) + { + LL_WARNS("ProfilePermissions") << "Trying to modify rights for non-friend avatar. Skipped." << LL_ENDL; + return; + } + + S32 rights = 0; + + if (mOnlineStatus->getValue().asBoolean()) + { + rights |= LLRelationship::GRANT_ONLINE_STATUS; + } + if (mMapRights->getValue().asBoolean()) + { + rights |= LLRelationship::GRANT_MAP_LOCATION; + } + if (mEditObjectRights->getValue().asBoolean()) + { + rights |= LLRelationship::GRANT_MODIFY_OBJECTS; + } + + LLAvatarPropertiesProcessor::getInstance()->sendFriendRights(mAvatarID, rights); + + closeFloater(); +} + +void LLFloaterProfilePermissions::onCancel() +{ + closeFloater(); +} + +////////////////////////////////////////////////////////////////////////// +// LLPanelProfileSecondLife + +LLPanelProfileSecondLife::LLPanelProfileSecondLife() + : LLPanelProfilePropertiesProcessorTab() + , mAvatarNameCacheConnection() + , mHasUnsavedDescriptionChanges(false) + , mWaitingForImageUpload(false) + , mAllowPublish(false) + , mHideAge(false) +{ +} + +LLPanelProfileSecondLife::~LLPanelProfileSecondLife() +{ + if (getAvatarId().notNull()) + { + LLAvatarTracker::instance().removeParticularFriendObserver(getAvatarId(), this); + } + + if (LLVoiceClient::instanceExists()) + { + LLVoiceClient::getInstance()->removeObserver((LLVoiceClientStatusObserver*)this); + } + + if (mAvatarNameCacheConnection.connected()) + { + mAvatarNameCacheConnection.disconnect(); + } +} + +bool LLPanelProfileSecondLife::postBuild() +{ + mGroupList = getChild("group_list"); + mShowInSearchCombo = getChild("show_in_search"); + mHideAgeCombo = getChild("hide_age"); + mSecondLifePic = getChild("2nd_life_pic"); + mSecondLifePicLayout = getChild("image_panel"); + mDescriptionEdit = getChild("sl_description_edit"); + mAgentActionMenuButton = getChild("agent_actions_menu"); + mSaveDescriptionChanges = getChild("save_description_changes"); + mDiscardDescriptionChanges = getChild("discard_description_changes"); + mCanSeeOnlineIcon = getChild("can_see_online"); + mCantSeeOnlineIcon = getChild("cant_see_online"); + mCanSeeOnMapIcon = getChild("can_see_on_map"); + mCantSeeOnMapIcon = getChild("cant_see_on_map"); + mCanEditObjectsIcon = getChild("can_edit_objects"); + mCantEditObjectsIcon = getChild("cant_edit_objects"); + + mShowInSearchCombo->setCommitCallback([this](LLUICtrl*, void*) { onShowInSearchCallback(); }, nullptr); + mHideAgeCombo->setCommitCallback([this](LLUICtrl*, void*) { onHideAgeCallback(); }, nullptr); + 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); + mDescriptionEdit->setKeystrokeCallback([this](LLTextEditor* caller) { onSetDescriptionDirty(); }); + + mCanSeeOnlineIcon->setMouseUpCallback([this](LLUICtrl*, S32 x, S32 y, MASK mask) { onShowAgentPermissionsDialog(); }); + mCantSeeOnlineIcon->setMouseUpCallback([this](LLUICtrl*, S32 x, S32 y, MASK mask) { onShowAgentPermissionsDialog(); }); + mCanSeeOnMapIcon->setMouseUpCallback([this](LLUICtrl*, S32 x, S32 y, MASK mask) { onShowAgentPermissionsDialog(); }); + mCantSeeOnMapIcon->setMouseUpCallback([this](LLUICtrl*, S32 x, S32 y, MASK mask) { onShowAgentPermissionsDialog(); }); + mCanEditObjectsIcon->setMouseUpCallback([this](LLUICtrl*, S32 x, S32 y, MASK mask) { onShowAgentPermissionsDialog(); }); + mCantEditObjectsIcon->setMouseUpCallback([this](LLUICtrl*, S32 x, S32 y, MASK mask) { onShowAgentPermissionsDialog(); }); + mSecondLifePic->setMouseUpCallback([this](LLUICtrl*, S32 x, S32 y, MASK mask) { onShowAgentProfileTexture(); }); + + return true; +} + +void LLPanelProfileSecondLife::onOpen(const LLSD& key) +{ + LLPanelProfileTab::onOpen(key); + + resetData(); + + LLUUID avatar_id = getAvatarId(); + + bool own_profile = getSelfProfile(); + + mGroupList->setShowNone(!own_profile); + + childSetVisible("notes_panel", !own_profile); + childSetVisible("settings_panel", own_profile); + childSetVisible("about_buttons_panel", own_profile); + + if (own_profile) + { + // Group list control cannot toggle ForAgent loading + // Less than ideal, but viewing own profile via search is edge case + mGroupList->enableForAgent(false); + } + + // Init menu, menu needs to be created in scope of a registar to work correctly. + LLUICtrl::CommitCallbackRegistry::ScopedRegistrar commit; + commit.add("Profile.Commit", [this](LLUICtrl*, const LLSD& userdata) { onCommitMenu(userdata); }); + + LLUICtrl::EnableCallbackRegistry::ScopedRegistrar enable; + enable.add("Profile.EnableItem", [this](LLUICtrl*, const LLSD& userdata) { return onEnableMenu(userdata); }); + enable.add("Profile.CheckItem", [this](LLUICtrl*, const LLSD& userdata) { return onCheckMenu(userdata); }); + + if (own_profile) + { + mAgentActionMenuButton->setMenu("menu_profile_self.xml", LLMenuButton::MP_BOTTOM_RIGHT); + } + else + { + // Todo: use PeopleContextMenu instead? + mAgentActionMenuButton->setMenu("menu_profile_other.xml", LLMenuButton::MP_BOTTOM_RIGHT); + } + + mDescriptionEdit->setParseHTML(!own_profile); + + if (!own_profile) + { + mVoiceStatus = LLAvatarActions::canCall() && (LLAvatarActions::isFriend(avatar_id) ? LLAvatarTracker::instance().isBuddyOnline(avatar_id) : true); + updateOnlineStatus(); + fillRightsData(); + } + + mAvatarNameCacheConnection = LLAvatarNameCache::get(getAvatarId(), boost::bind(&LLPanelProfileSecondLife::onAvatarNameCache, this, _1, _2)); +} + + +bool LLPanelProfileSecondLife::handleDragAndDrop(S32 x, S32 y, MASK mask, bool drop, + EDragAndDropType cargo_type, + void* cargo_data, + EAcceptance* accept, + std::string& tooltip_msg) +{ + // Try children first + if (LLPanelProfileTab::handleDragAndDrop(x, y, mask, drop, cargo_type, cargo_data, accept, tooltip_msg) + && *accept != ACCEPT_NO) + { + return true; + } + + // No point sharing with own profile + if (getSelfProfile()) + { + return false; + } + + // Exclude fields that look like they are editable. + S32 child_x = 0; + S32 child_y = 0; + if (localPointToOtherView(x, y, &child_x, &child_y, mDescriptionEdit) + && mDescriptionEdit->pointInView(child_x, child_y)) + { + return false; + } + + if (localPointToOtherView(x, y, &child_x, &child_y, mGroupList) + && mGroupList->pointInView(child_x, child_y)) + { + return false; + } + + // Share + LLToolDragAndDrop::handleGiveDragAndDrop(getAvatarId(), + LLUUID::null, + drop, + cargo_type, + cargo_data, + accept); + return true; +} + +void LLPanelProfileSecondLife::refreshName() +{ + if (!mAvatarNameCacheConnection.connected()) + { + mAvatarNameCacheConnection = LLAvatarNameCache::get(getAvatarId(), boost::bind(&LLPanelProfileSecondLife::onAvatarNameCache, this, _1, _2)); + } +} + +void LLPanelProfileSecondLife::resetData() +{ + resetLoading(); + + // Set default image and 1:1 dimensions for it + mSecondLifePic->setValue("Generic_Person_Large"); + + LLRect imageRect = mSecondLifePicLayout->getRect(); + mSecondLifePicLayout->reshape(imageRect.getWidth(), imageRect.getWidth()); + + setDescriptionText(LLStringUtil::null); + mGroups.clear(); + mGroupList->setGroups(mGroups); + + bool own_profile = getSelfProfile(); + mCanSeeOnlineIcon->setVisible(false); + mCantSeeOnlineIcon->setVisible(!own_profile); + mCanSeeOnMapIcon->setVisible(false); + mCantSeeOnMapIcon->setVisible(!own_profile); + mCanEditObjectsIcon->setVisible(false); + mCantEditObjectsIcon->setVisible(!own_profile); + + mCanSeeOnlineIcon->setEnabled(false); + mCantSeeOnlineIcon->setEnabled(false); + mCanSeeOnMapIcon->setEnabled(false); + mCantSeeOnMapIcon->setEnabled(false); + mCanEditObjectsIcon->setEnabled(false); + mCantEditObjectsIcon->setEnabled(false); + + childSetVisible("partner_layout", false); + childSetVisible("badge_layout", false); + childSetVisible("partner_spacer_layout", true); +} + +void LLPanelProfileSecondLife::processProperties(void* data, EAvatarProcessorType type) +{ + if (APT_PROPERTIES == type) + { + LLAvatarData* avatar_data = static_cast(data); + if (avatar_data && getAvatarId() == avatar_data->avatar_id) + { + processProfileProperties(avatar_data); + } + } +} + +void LLPanelProfileSecondLife::processProfileProperties(const LLAvatarData* avatar_data) +{ + const LLRelationship* relationship = LLAvatarTracker::instance().getBuddyInfo(getAvatarId()); + if ((relationship != NULL || gAgent.isGodlike()) && !getSelfProfile()) + { + // Relies onto friend observer to get information about online status updates. + // Once SL-17506 gets implemented, condition might need to become: + // (gAgent.isGodlike() || isRightGrantedFrom || flags & AVATAR_ONLINE) + processOnlineStatus(relationship != NULL, + gAgent.isGodlike() || relationship->isRightGrantedFrom(LLRelationship::GRANT_ONLINE_STATUS), + (avatar_data->flags & AVATAR_ONLINE)); + } + + fillCommonData(avatar_data); + + fillPartnerData(avatar_data); + + fillAccountStatus(avatar_data); + + LLAvatarData::group_list_t::const_iterator it = avatar_data->group_list.begin(); + const LLAvatarData::group_list_t::const_iterator it_end = avatar_data->group_list.end(); + + for (; it_end != it; ++it) + { + LLAvatarData::LLGroupData group_data = *it; + mGroups[group_data.group_name] = group_data.group_id; + } + + mGroupList->setGroups(mGroups); + + setLoaded(); +} + +void LLPanelProfileSecondLife::openGroupProfile() +{ + LLUUID group_id = mGroupList->getSelectedUUID(); + LLGroupActions::show(group_id); +} + +void LLPanelProfileSecondLife::onAvatarNameCache(const LLUUID& agent_id, const LLAvatarName& av_name) +{ + mAvatarNameCacheConnection.disconnect(); + getChild("display_name")->setValue(av_name.getDisplayName()); + getChild("user_name")->setValue(av_name.getAccountName()); +} + +void LLPanelProfileSecondLife::setProfileImageUploading(bool loading) +{ + LLLoadingIndicator* indicator = getChild("image_upload_indicator"); + indicator->setVisible(loading); + if (loading) + { + indicator->start(); + } + else + { + indicator->stop(); + } + mWaitingForImageUpload = loading; +} + +void LLPanelProfileSecondLife::setProfileImageUploaded(const LLUUID &image_asset_id) +{ + mSecondLifePic->setValue(image_asset_id); + + LLFloater *floater = mFloaterProfileTextureHandle.get(); + if (floater) + { + LLFloaterProfileTexture * texture_view = dynamic_cast(floater); + texture_view->loadAsset(mSecondLifePic->getImageAssetId()); + } + + setProfileImageUploading(false); +} + +bool LLPanelProfileSecondLife::hasUnsavedChanges() +{ + LLFloater *floater = mFloaterPermissionsHandle.get(); + if (floater) + { + LLFloaterProfilePermissions* perm = dynamic_cast(floater); + if (perm && perm->hasUnsavedChanges()) + { + return true; + } + } + // if floater + return mHasUnsavedDescriptionChanges; +} + +void LLPanelProfileSecondLife::commitUnsavedChanges() +{ + LLFloater *floater = mFloaterPermissionsHandle.get(); + if (floater) + { + LLFloaterProfilePermissions* perm = dynamic_cast(floater); + if (perm && perm->hasUnsavedChanges()) + { + perm->onApplyRights(); + } + } + if (mHasUnsavedDescriptionChanges) + { + onSaveDescriptionChanges(); + } +} + +void LLPanelProfileSecondLife::fillCommonData(const LLAvatarData* avatar_data) +{ + // Refresh avatar id in cache with new info to prevent re-requests + // and to make sure icons in text will be up to date + LLAvatarIconIDCache::getInstance()->add(avatar_data->avatar_id, avatar_data->image_id); + + fillAgeData(avatar_data); + + setDescriptionText(avatar_data->about_text); + + mSecondLifePic->setValue(avatar_data->image_id); + + if (getSelfProfile()) + { + mAllowPublish = avatar_data->flags & AVATAR_ALLOW_PUBLISH; + mShowInSearchCombo->setValue(mAllowPublish); + } +} + +void LLPanelProfileSecondLife::fillPartnerData(const LLAvatarData* avatar_data) +{ + LLTextBox* partner_text_ctrl = getChild("partner_link"); + if (avatar_data->partner_id.notNull()) + { + childSetVisible("partner_layout", true); + LLStringUtil::format_map_t args; + args["[LINK]"] = LLSLURL("agent", avatar_data->partner_id, "inspect").getSLURLString(); + std::string partner_text = getString("partner_text", args); + partner_text_ctrl->setText(partner_text); + } + else + { + childSetVisible("partner_layout", false); + } +} + +void LLPanelProfileSecondLife::fillAccountStatus(const LLAvatarData* avatar_data) +{ + LLStringUtil::format_map_t args; + args["[ACCTTYPE]"] = LLAvatarPropertiesProcessor::accountType(avatar_data); + args["[PAYMENTINFO]"] = LLAvatarPropertiesProcessor::paymentInfo(avatar_data); + + std::string caption_text = getString("CaptionTextAcctInfo", args); + getChild("account_info")->setValue(caption_text); + + const S32 LINDEN_EMPLOYEE_INDEX = 3; + LLDate sl_release; + sl_release.fromYMDHMS(2003, 6, 23, 0, 0, 0); + std::string customer_lower = avatar_data->customer_type; + LLStringUtil::toLower(customer_lower); + if (avatar_data->caption_index == LINDEN_EMPLOYEE_INDEX) + { + getChild("badge_icon")->setValue("Profile_Badge_Linden"); + getChild("badge_text")->setValue(getString("BadgeLinden")); + childSetVisible("badge_layout", true); + childSetVisible("partner_spacer_layout", false); + } + else if (avatar_data->born_on < sl_release) + { + getChild("badge_icon")->setValue("Profile_Badge_Beta"); + getChild("badge_text")->setValue(getString("BadgeBeta")); + childSetVisible("badge_layout", true); + childSetVisible("partner_spacer_layout", false); + } + else if (customer_lower == "beta_lifetime") + { + getChild("badge_icon")->setValue("Profile_Badge_Beta_Lifetime"); + getChild("badge_text")->setValue(getString("BadgeBetaLifetime")); + childSetVisible("badge_layout", true); + childSetVisible("partner_spacer_layout", false); + } + else if (customer_lower == "lifetime") + { + getChild("badge_icon")->setValue("Profile_Badge_Lifetime"); + getChild("badge_text")->setValue(getString("BadgeLifetime")); + childSetVisible("badge_layout", true); + childSetVisible("partner_spacer_layout", false); + } + else if (customer_lower == "secondlifetime_premium") + { + getChild("badge_icon")->setValue("Profile_Badge_Premium_Lifetime"); + getChild("badge_text")->setValue(getString("BadgePremiumLifetime")); + childSetVisible("badge_layout", true); + childSetVisible("partner_spacer_layout", false); + } + else if (customer_lower == "secondlifetime_premium_plus") + { + getChild("badge_icon")->setValue("Profile_Badge_Pplus_Lifetime"); + getChild("badge_text")->setValue(getString("BadgePremiumPlusLifetime")); + childSetVisible("badge_layout", true); + childSetVisible("partner_spacer_layout", false); + } + else + { + childSetVisible("badge_layout", false); + childSetVisible("partner_spacer_layout", true); + } +} + +void LLPanelProfileSecondLife::fillRightsData() +{ + if (getSelfProfile()) + { + return; + } + + const LLRelationship* relation = LLAvatarTracker::instance().getBuddyInfo(getAvatarId()); + // If true - we are viewing friend's profile, enable check boxes and set values. + if (relation) + { + S32 rights = relation->getRightsGrantedTo(); + bool can_see_online = LLRelationship::GRANT_ONLINE_STATUS & rights; + bool can_see_on_map = LLRelationship::GRANT_MAP_LOCATION & rights; + bool can_edit_objects = LLRelationship::GRANT_MODIFY_OBJECTS & rights; + + mCanSeeOnlineIcon->setVisible(can_see_online); + mCantSeeOnlineIcon->setVisible(!can_see_online); + mCanSeeOnMapIcon->setVisible(can_see_on_map); + mCantSeeOnMapIcon->setVisible(!can_see_on_map); + mCanEditObjectsIcon->setVisible(can_edit_objects); + mCantEditObjectsIcon->setVisible(!can_edit_objects); + + mCanSeeOnlineIcon->setEnabled(true); + mCantSeeOnlineIcon->setEnabled(true); + mCanSeeOnMapIcon->setEnabled(true); + mCantSeeOnMapIcon->setEnabled(true); + mCanEditObjectsIcon->setEnabled(true); + mCantEditObjectsIcon->setEnabled(true); + } + else + { + mCanSeeOnlineIcon->setVisible(false); + mCantSeeOnlineIcon->setVisible(false); + mCanSeeOnMapIcon->setVisible(false); + mCantSeeOnMapIcon->setVisible(false); + mCanEditObjectsIcon->setVisible(false); + mCantEditObjectsIcon->setVisible(false); + } +} + +void LLPanelProfileSecondLife::fillAgeData(const LLAvatarData* avatar_data) +{ + // Date from server comes already converted to stl timezone, + // so display it as an UTC + 0 + bool hide_age = avatar_data->hide_age && !getSelfProfile(); + std::string name_and_date = getString(hide_age ? "date_format_short" : "date_format_full"); + LLSD args_name; + args_name["datetime"] = (S32)avatar_data->born_on.secondsSinceEpoch(); + LLStringUtil::format(name_and_date, args_name); + getChild("sl_birth_date")->setValue(name_and_date); + + LLUICtrl* userAgeCtrl = getChild("user_age"); + if (hide_age) + { + userAgeCtrl->setVisible(false); + } + else + { + std::string register_date = getString("age_format"); + LLSD args_age; + args_age["[AGE]"] = LLDateUtil::ageFromDate(avatar_data->born_on, LLDate::now()); + LLStringUtil::format(register_date, args_age); + userAgeCtrl->setValue(register_date); + } + + bool showHideAgeCombo = false; + if (getSelfProfile()) + { + if (LLAvatarPropertiesProcessor::getInstance()->isHideAgeSupportedByServer()) + { + F64 birth = avatar_data->born_on.secondsSinceEpoch(); + F64 now = LLDate::now().secondsSinceEpoch(); + if (now - birth > 365 * 24 * 60 * 60) + { + mHideAge = avatar_data->hide_age; + mHideAgeCombo->setValue(mHideAge); + showHideAgeCombo = true; + } + } + } + mHideAgeCombo->setVisible(showHideAgeCombo); +} + +void LLPanelProfileSecondLife::onImageLoaded(bool success, LLViewerFetchedTexture *imagep) +{ + LLRect imageRect = mSecondLifePicLayout->getRect(); + if (!success || imagep->getFullWidth() == imagep->getFullHeight()) + { + mSecondLifePicLayout->reshape(imageRect.getWidth(), imageRect.getWidth()); + } + else + { + // assume 3:4, for sake of firestorm + mSecondLifePicLayout->reshape(imageRect.getWidth(), imageRect.getWidth() * 3 / 4); + } +} + +// virtual, called by LLAvatarTracker +void LLPanelProfileSecondLife::changed(U32 mask) +{ + updateOnlineStatus(); + if (mask != LLFriendObserver::ONLINE) + { + fillRightsData(); + } +} + +// virtual, called by LLVoiceClient +void LLPanelProfileSecondLife::onChange(EStatusType status, const std::string &channelURI, bool proximal) +{ + if(status == STATUS_JOINING || status == STATUS_LEFT_CHANNEL) + { + return; + } + + mVoiceStatus = LLAvatarActions::canCall() && (LLAvatarActions::isFriend(getAvatarId()) ? LLAvatarTracker::instance().isBuddyOnline(getAvatarId()) : true); +} + +void LLPanelProfileSecondLife::setAvatarId(const LLUUID& avatar_id) +{ + if (avatar_id.notNull()) + { + if (getAvatarId().notNull()) + { + LLAvatarTracker::instance().removeParticularFriendObserver(getAvatarId(), this); + } + + LLPanelProfilePropertiesProcessorTab::setAvatarId(avatar_id); + + if (LLAvatarActions::isFriend(getAvatarId())) + { + LLAvatarTracker::instance().addParticularFriendObserver(getAvatarId(), this); + } + } +} + +// method was disabled according to EXT-2022. Re-enabled & improved according to EXT-3880 +void LLPanelProfileSecondLife::updateOnlineStatus() +{ + const LLRelationship* relationship = LLAvatarTracker::instance().getBuddyInfo(getAvatarId()); + if (relationship != NULL) + { + // For friend let check if he allowed me to see his status + bool online = relationship->isOnline(); + bool perm_granted = relationship->isRightGrantedFrom(LLRelationship::GRANT_ONLINE_STATUS); + processOnlineStatus(true, perm_granted, online); + } + else + { + childSetVisible("friend_layout", false); + childSetVisible("online_layout", false); + childSetVisible("offline_layout", false); + } +} + +void LLPanelProfileSecondLife::processOnlineStatus(bool is_friend, bool show_online, bool online) +{ + childSetVisible("friend_layout", is_friend); + childSetVisible("online_layout", online && show_online); + childSetVisible("offline_layout", !online && show_online); +} + +void LLPanelProfileSecondLife::setLoaded() +{ + LLPanelProfileTab::setLoaded(); + + if (getSelfProfile()) + { + mShowInSearchCombo->setEnabled(true); + if (mHideAgeCombo->getVisible()) + { + mHideAgeCombo->setEnabled(true); + } + mDescriptionEdit->setEnabled(true); + } +} + + +class LLProfileImagePicker : public LLFilePickerThread +{ +public: + LLProfileImagePicker(EProfileImageType type, LLHandle *handle); + ~LLProfileImagePicker(); + void notify(const std::vector& filenames) override; + +private: + LLHandle *mHandle; + EProfileImageType mType; +}; + +LLProfileImagePicker::LLProfileImagePicker(EProfileImageType type, LLHandle *handle) + : LLFilePickerThread(LLFilePicker::FFLOAD_IMAGE), + mHandle(handle), + mType(type) +{ +} + +LLProfileImagePicker::~LLProfileImagePicker() +{ + delete mHandle; +} + +void LLProfileImagePicker::notify(const std::vector& filenames) +{ + if (mHandle->isDead()) + { + return; + } + if (filenames.empty()) + { + return; + } + std::string file_path = filenames[0]; + if (file_path.empty()) + { + return; + } + + // generate a temp texture file for coroutine + std::string temp_file = gDirUtilp->getTempFilename(); + U32 codec = LLImageBase::getCodecFromExtension(gDirUtilp->getExtension(file_path)); + const S32 MAX_DIM = 256; + if (!LLViewerTextureList::createUploadFile(file_path, temp_file, codec, MAX_DIM)) + { + LLSD notif_args; + notif_args["REASON"] = LLImage::getLastThreadError().c_str(); + LLNotificationsUtil::add("CannotUploadTexture", notif_args); + LL_WARNS("AvatarProperties") << "Failed to upload profile image of type " << (S32)mType << ", " << notif_args["REASON"].asString() << LL_ENDL; + return; + } + + std::string cap_url = gAgent.getRegionCapability(PROFILE_IMAGE_UPLOAD_CAP); + if (cap_url.empty()) + { + LLSD args; + args["CAPABILITY"] = PROFILE_IMAGE_UPLOAD_CAP; + LLNotificationsUtil::add("RegionCapabilityRequestError", args); + LL_WARNS("AvatarProperties") << "Failed to upload profile image of type " << (S32)mType << ", no cap found" << LL_ENDL; + return; + } + + switch (mType) + { + case PROFILE_IMAGE_SL: + { + LLPanelProfileSecondLife* panel = static_cast(mHandle->get()); + panel->setProfileImageUploading(true); + } + break; + case PROFILE_IMAGE_FL: + { + LLPanelProfileFirstLife* panel = static_cast(mHandle->get()); + panel->setProfileImageUploading(true); + } + break; + } + + 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) +{ + const std::string item_name = userdata.asString(); + const LLUUID agent_id = getAvatarId(); + // todo: consider moving this into LLAvatarActions::onCommit(name, id) + // and making all other flaoters, like people menu do the same + if (item_name == "im") + { + LLAvatarActions::startIM(agent_id); + } + else if (item_name == "offer_teleport") + { + LLAvatarActions::offerTeleport(agent_id); + } + else if (item_name == "request_teleport") + { + LLAvatarActions::teleportRequest(agent_id); + } + else if (item_name == "voice_call") + { + LLAvatarActions::startCall(agent_id); + } + else if (item_name == "chat_history") + { + LLAvatarActions::viewChatHistory(agent_id); + } + else if (item_name == "add_friend") + { + LLAvatarActions::requestFriendshipDialog(agent_id); + } + else if (item_name == "remove_friend") + { + LLAvatarActions::removeFriendDialog(agent_id); + } + else if (item_name == "invite_to_group") + { + LLAvatarActions::inviteToGroup(agent_id); + } + else if (item_name == "can_show_on_map") + { + LLAvatarActions::showOnMap(agent_id); + } + else if (item_name == "share") + { + LLAvatarActions::share(agent_id); + } + else if (item_name == "pay") + { + LLAvatarActions::pay(agent_id); + } + else if (item_name == "toggle_block_agent") + { + 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 == "agent_permissions") + { + onShowAgentPermissionsDialog(); + } + 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") + { + std::string url = "https://[GRID]/my/account/partners.php"; + LLSD subs; + url = LLWeb::expandURLSubstitutions(url, subs); + LLUrlAction::openURL(url); + } + else if (item_name == "upload_photo") + { + (new LLProfileImagePicker(PROFILE_IMAGE_SL, new LLHandle(LLPanel::getHandle())))->getFile(); + + LLFloater* floaterp = mFloaterTexturePickerHandle.get(); + if (floaterp) + { + floaterp->closeFloater(); + } + } + else if (item_name == "change_photo") + { + onShowTexturePicker(); + } + else if (item_name == "remove_photo") + { + onCommitProfileImage(LLUUID::null); + + LLFloater* floaterp = mFloaterTexturePickerHandle.get(); + if (floaterp) + { + floaterp->closeFloater(); + } + } +} + +bool LLPanelProfileSecondLife::onEnableMenu(const LLSD& userdata) +{ + const std::string item_name = userdata.asString(); + const LLUUID agent_id = getAvatarId(); + if (item_name == "offer_teleport" || item_name == "request_teleport") + { + return LLAvatarActions::canOfferTeleport(agent_id); + } + else if (item_name == "voice_call") + { + return mVoiceStatus; + } + else if (item_name == "chat_history") + { + return LLLogChat::isTranscriptExist(agent_id); + } + else if (item_name == "add_friend") + { + return !LLAvatarActions::isFriend(agent_id); + } + else if (item_name == "remove_friend") + { + return LLAvatarActions::isFriend(agent_id); + } + else if (item_name == "can_show_on_map") + { + return (LLAvatarTracker::instance().isBuddyOnline(agent_id) && is_agent_mappable(agent_id)) + || gAgent.isGodlike(); + } + else if (item_name == "toggle_block_agent") + { + return LLAvatarActions::canBlock(agent_id); + } + else if (item_name == "agent_permissions") + { + return LLAvatarActions::isFriend(agent_id); + } + else if (item_name == "copy_display_name" + || item_name == "copy_username") + { + return !mAvatarNameCacheConnection.connected(); + } + else if (item_name == "upload_photo" + || item_name == "change_photo") + { + std::string cap_url = gAgent.getRegionCapability(PROFILE_IMAGE_UPLOAD_CAP); + return !cap_url.empty() && !mWaitingForImageUpload && getIsLoaded(); + } + else if (item_name == "remove_photo") + { + std::string cap_url = gAgent.getRegionCapability(PROFILE_PROPERTIES_CAP); + return mSecondLifePic->getImageAssetId().notNull() && !cap_url.empty() && !mWaitingForImageUpload && getIsLoaded(); + } + + return false; +} + +bool LLPanelProfileSecondLife::onCheckMenu(const LLSD& userdata) +{ + const std::string item_name = userdata.asString(); + const LLUUID agent_id = getAvatarId(); + if (item_name == "toggle_block_agent") + { + return LLAvatarActions::isBlocked(agent_id); + } + return false; +} + +void LLPanelProfileSecondLife::onAvatarNameCacheSetName(const LLUUID& agent_id, const LLAvatarName& av_name) +{ + if (av_name.getDisplayName().empty()) + { + // something is wrong, tell user to try again later + LLNotificationsUtil::add("SetDisplayNameFailedGeneric"); + return; + } + + LL_INFOS("LegacyProfile") << "name-change now " << LLDate::now() << " next_update " + << LLDate(av_name.mNextUpdate) << LL_ENDL; + F64 now_secs = LLDate::now().secondsSinceEpoch(); + + if (now_secs < av_name.mNextUpdate) + { + // if the update time is more than a year in the future, it means updates have been blocked + // show a more general message + static const S32 YEAR = 60*60*24*365; + if (now_secs + YEAR < av_name.mNextUpdate) + { + LLNotificationsUtil::add("SetDisplayNameBlocked"); + return; + } + } + + LLFloaterReg::showInstance("display_name"); +} + +void LLPanelProfileSecondLife::setDescriptionText(const std::string &text) +{ + mSaveDescriptionChanges->setEnabled(false); + mDiscardDescriptionChanges->setEnabled(false); + mHasUnsavedDescriptionChanges = false; + + mDescriptionText = text; + mDescriptionEdit->setValue(mDescriptionText); +} + +void LLPanelProfileSecondLife::onSetDescriptionDirty() +{ + mSaveDescriptionChanges->setEnabled(true); + mDiscardDescriptionChanges->setEnabled(true); + mHasUnsavedDescriptionChanges = true; +} + +void LLPanelProfileSecondLife::onShowInSearchCallback() +{ + bool value = mShowInSearchCombo->getValue().asInteger(); + if (value == mAllowPublish) + return; + + mAllowPublish = value; + saveAgentUserInfoCoro("allow_publish", value); +} + +void LLPanelProfileSecondLife::onHideAgeCallback() +{ + bool value = mHideAgeCombo->getValue().asInteger(); + if (value == mHideAge) + return; + + mHideAge = value; + saveAgentUserInfoCoro("hide_age", value); +} + +void LLPanelProfileSecondLife::onSaveDescriptionChanges() +{ + mDescriptionText = mDescriptionEdit->getValue().asString(); + saveAgentUserInfoCoro("sl_about_text", mDescriptionText); + + mSaveDescriptionChanges->setEnabled(false); + mDiscardDescriptionChanges->setEnabled(false); + mHasUnsavedDescriptionChanges = false; +} + +void LLPanelProfileSecondLife::onDiscardDescriptionChanges() +{ + setDescriptionText(mDescriptionText); +} + +void LLPanelProfileSecondLife::onShowAgentPermissionsDialog() +{ + LLFloater *floater = mFloaterPermissionsHandle.get(); + if (!floater) + { + LLFloater* parent_floater = gFloaterView->getParentFloater(this); + if (parent_floater) + { + LLFloaterProfilePermissions * perms = new LLFloaterProfilePermissions(parent_floater, getAvatarId()); + mFloaterPermissionsHandle = perms->getHandle(); + perms->openFloater(); + perms->setVisibleAndFrontmost(true); + + parent_floater->addDependentFloater(mFloaterPermissionsHandle); + } + } + else // already open + { + floater->setMinimized(false); + floater->setVisibleAndFrontmost(true); + } +} + +void LLPanelProfileSecondLife::onShowAgentProfileTexture() +{ + if (!getIsLoaded()) + { + return; + } + + LLFloater *floater = mFloaterProfileTextureHandle.get(); + if (!floater) + { + LLFloater* parent_floater = gFloaterView->getParentFloater(this); + if (parent_floater) + { + LLFloaterProfileTexture * texture_view = new LLFloaterProfileTexture(parent_floater); + mFloaterProfileTextureHandle = texture_view->getHandle(); + if (mSecondLifePic->getImageAssetId().notNull()) + { + texture_view->loadAsset(mSecondLifePic->getImageAssetId()); + } + else + { + texture_view->resetAsset(); + } + texture_view->openFloater(); + texture_view->setVisibleAndFrontmost(true); + + parent_floater->addDependentFloater(mFloaterProfileTextureHandle); + } + } + else // already open + { + LLFloaterProfileTexture * texture_view = dynamic_cast(floater); + texture_view->setMinimized(false); + texture_view->setVisibleAndFrontmost(true); + if (mSecondLifePic->getImageAssetId().notNull()) + { + texture_view->loadAsset(mSecondLifePic->getImageAssetId()); + } + else + { + texture_view->resetAsset(); + } + } +} + +void LLPanelProfileSecondLife::onShowTexturePicker() +{ + LLFloater* floaterp = mFloaterTexturePickerHandle.get(); + + // Show the dialog + if (!floaterp) + { + LLFloater* parent_floater = gFloaterView->getParentFloater(this); + if (parent_floater) + { + // because inventory construction is somewhat slow + getWindow()->setCursor(UI_CURSOR_WAIT); + LLFloaterTexturePicker* texture_floaterp = new LLFloaterTexturePicker( + this, + mSecondLifePic->getImageAssetId(), + LLUUID::null, + mSecondLifePic->getImageAssetId(), + false, + false, + "SELECT PHOTO", + PERM_NONE, + PERM_NONE, + false, + NULL, + PICK_TEXTURE); + + mFloaterTexturePickerHandle = texture_floaterp->getHandle(); + + texture_floaterp->setOnFloaterCommitCallback([this](LLTextureCtrl::ETexturePickOp op, LLPickerSource source, const LLUUID& asset_id, const LLUUID&, const LLUUID&) + { + if (op == LLTextureCtrl::TEXTURE_SELECT) + { + onCommitProfileImage(asset_id); + } + }); + texture_floaterp->setLocalTextureEnabled(false); + texture_floaterp->setBakeTextureEnabled(false); + texture_floaterp->setCanApply(false, true, false); + + parent_floater->addDependentFloater(mFloaterTexturePickerHandle); + + texture_floaterp->openFloater(); + texture_floaterp->setFocus(true); + } + } + else + { + floaterp->setMinimized(false); + floaterp->setVisibleAndFrontmost(true); + } +} + +void LLPanelProfileSecondLife::onCommitProfileImage(const LLUUID& id) +{ + if (mSecondLifePic->getImageAssetId() == id) + return; + + std::function callback = [id](bool result) + { + if (result) + { + LLAvatarIconIDCache::getInstance()->add(gAgentID, id); + // Should trigger callbacks in icon controls (or request Legacy) + LLAvatarPropertiesProcessor::getInstance()->sendAvatarPropertiesRequest(gAgentID); + } + }; + + if (!saveAgentUserInfoCoro("sl_image_id", id, callback)) + return; + + mSecondLifePic->setValue(id); + + LLFloater *floater = mFloaterProfileTextureHandle.get(); + if (floater) + { + LLFloaterProfileTexture * texture_view = dynamic_cast(floater); + if (id == LLUUID::null) + { + texture_view->resetAsset(); + } + else + { + texture_view->loadAsset(id); + } + } +} + +////////////////////////////////////////////////////////////////////////// +// LLPanelProfileWeb + +LLPanelProfileWeb::LLPanelProfileWeb() + : LLPanelProfileTab() + , mWebBrowser(NULL) + , mAvatarNameCacheConnection() +{ +} + +LLPanelProfileWeb::~LLPanelProfileWeb() +{ + if (mAvatarNameCacheConnection.connected()) + { + mAvatarNameCacheConnection.disconnect(); + } +} + +void LLPanelProfileWeb::onOpen(const LLSD& key) +{ + LLPanelProfileTab::onOpen(key); + + resetData(); + + mAvatarNameCacheConnection = LLAvatarNameCache::get(getAvatarId(), boost::bind(&LLPanelProfileWeb::onAvatarNameCache, this, _1, _2)); +} + +bool LLPanelProfileWeb::postBuild() +{ + mWebBrowser = getChild("profile_html"); + mWebBrowser->addObserver(this); + mWebBrowser->setHomePageUrl("about:blank"); + + return true; +} + +void LLPanelProfileWeb::resetData() +{ + mWebBrowser->navigateHome(); +} + +void LLPanelProfileWeb::updateData() +{ + LLUUID avatar_id = getAvatarId(); + if (!getStarted() && avatar_id.notNull() && !mURLWebProfile.empty()) + { + setIsLoading(); + + mWebBrowser->setVisible(true); + mPerformanceTimer.start(); + mWebBrowser->navigateTo(mURLWebProfile, HTTP_CONTENT_TEXT_HTML); + } +} + +void LLPanelProfileWeb::onAvatarNameCache(const LLUUID& agent_id, const LLAvatarName& av_name) +{ + mAvatarNameCacheConnection.disconnect(); + + std::string username = av_name.getAccountName(); + if (username.empty()) + { + username = LLCacheName::buildUsername(av_name.getDisplayName()); + } + else + { + LLStringUtil::replaceChar(username, ' ', '.'); + } + + mURLWebProfile = getProfileURL(username, true); + if (mURLWebProfile.empty()) + { + return; + } + + //if the tab was opened before name was resolved, load the panel now + updateData(); +} + +void LLPanelProfileWeb::onCommitLoad(LLUICtrl* ctrl) +{ + if (!mURLHome.empty()) + { + LLSD::String valstr = ctrl->getValue().asString(); + if (valstr.empty()) + { + mWebBrowser->setVisible(true); + mPerformanceTimer.start(); + mWebBrowser->navigateTo( mURLHome, HTTP_CONTENT_TEXT_HTML ); + } + else if (valstr == "popout") + { + // open in viewer's browser, new window + LLWeb::loadURLInternal(mURLHome); + } + else if (valstr == "external") + { + // open in external browser + LLWeb::loadURLExternal(mURLHome); + } + } +} + +void LLPanelProfileWeb::handleMediaEvent(LLPluginClassMedia* self, EMediaEvent event) +{ + switch(event) + { + case MEDIA_EVENT_STATUS_TEXT_CHANGED: + childSetValue("status_text", LLSD( self->getStatusText() ) ); + break; + + case MEDIA_EVENT_NAVIGATE_BEGIN: + { + if (mFirstNavigate) + { + mFirstNavigate = false; + } + else + { + mPerformanceTimer.start(); + } + } + break; + + case MEDIA_EVENT_NAVIGATE_COMPLETE: + { + LLStringUtil::format_map_t args; + args["[TIME]"] = llformat("%.2f", mPerformanceTimer.getElapsedTimeF32()); + childSetValue("status_text", LLSD( getString("LoadTime", args)) ); + + setLoaded(); + } + break; + + default: + // Having a default case makes the compiler happy. + break; + } +} + + +////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// + +LLPanelProfileFirstLife::LLPanelProfileFirstLife() + : LLPanelProfilePropertiesProcessorTab() + , mHasUnsavedChanges(false) +{ +} + +LLPanelProfileFirstLife::~LLPanelProfileFirstLife() +{ +} + +bool LLPanelProfileFirstLife::postBuild() +{ + mDescriptionEdit = getChild("fl_description_edit"); + mPicture = getChild("real_world_pic"); + + mUploadPhoto = getChild("fl_upload_image"); + mChangePhoto = getChild("fl_change_image"); + mRemovePhoto = getChild("fl_remove_image"); + mSaveChanges = getChild("fl_save_changes"); + mDiscardChanges = getChild("fl_discard_changes"); + + mUploadPhoto->setCommitCallback([this](LLUICtrl*, void*) { onUploadPhoto(); }, nullptr); + mChangePhoto->setCommitCallback([this](LLUICtrl*, void*) { onChangePhoto(); }, nullptr); + mRemovePhoto->setCommitCallback([this](LLUICtrl*, void*) { onRemovePhoto(); }, nullptr); + mSaveChanges->setCommitCallback([this](LLUICtrl*, void*) { onSaveDescriptionChanges(); }, nullptr); + mDiscardChanges->setCommitCallback([this](LLUICtrl*, void*) { onDiscardDescriptionChanges(); }, nullptr); + mDescriptionEdit->setKeystrokeCallback([this](LLTextEditor* caller) { onSetDescriptionDirty(); }); + + return true; +} + +void LLPanelProfileFirstLife::onOpen(const LLSD& key) +{ + LLPanelProfileTab::onOpen(key); + + if (!getSelfProfile()) + { + // Otherwise as the only focusable element it will be selected + mDescriptionEdit->setTabStop(false); + } + + resetData(); +} + +void LLPanelProfileFirstLife::setProfileImageUploading(bool loading) +{ + mUploadPhoto->setEnabled(!loading); + mChangePhoto->setEnabled(!loading); + mRemovePhoto->setEnabled(!loading && mPicture->getImageAssetId().notNull()); + + LLLoadingIndicator* indicator = getChild("image_upload_indicator"); + indicator->setVisible(loading); + if (loading) + { + indicator->start(); + } + else + { + indicator->stop(); + } +} + +void LLPanelProfileFirstLife::setProfileImageUploaded(const LLUUID &image_asset_id) +{ + mPicture->setValue(image_asset_id); + setProfileImageUploading(false); +} + +void LLPanelProfileFirstLife::commitUnsavedChanges() +{ + if (mHasUnsavedChanges) + { + onSaveDescriptionChanges(); + } +} + +void LLPanelProfileFirstLife::onUploadPhoto() +{ + (new LLProfileImagePicker(PROFILE_IMAGE_FL, new LLHandle(LLPanel::getHandle())))->getFile(); + + LLFloater* floaterp = mFloaterTexturePickerHandle.get(); + if (floaterp) + { + floaterp->closeFloater(); + } +} + +void LLPanelProfileFirstLife::onChangePhoto() +{ + LLFloater* floaterp = mFloaterTexturePickerHandle.get(); + + // Show the dialog + if (!floaterp) + { + LLFloater* parent_floater = gFloaterView->getParentFloater(this); + if (parent_floater) + { + // because inventory construction is somewhat slow + getWindow()->setCursor(UI_CURSOR_WAIT); + LLFloaterTexturePicker* texture_floaterp = new LLFloaterTexturePicker( + this, + mPicture->getImageAssetId(), + LLUUID::null, + mPicture->getImageAssetId(), + false, + false, + "SELECT PHOTO", + PERM_NONE, + PERM_NONE, + false, + NULL, + PICK_TEXTURE); + + mFloaterTexturePickerHandle = texture_floaterp->getHandle(); + + texture_floaterp->setOnFloaterCommitCallback([this](LLTextureCtrl::ETexturePickOp op, LLPickerSource source, const LLUUID& asset_id, const LLUUID&, const LLUUID&) + { + if (op == LLTextureCtrl::TEXTURE_SELECT) + { + onCommitPhoto(asset_id); + } + }); + texture_floaterp->setLocalTextureEnabled(false); + texture_floaterp->setCanApply(false, true, false); + + parent_floater->addDependentFloater(mFloaterTexturePickerHandle); + + texture_floaterp->openFloater(); + texture_floaterp->setFocus(true); + } + } + else + { + floaterp->setMinimized(false); + floaterp->setVisibleAndFrontmost(true); + } +} + +void LLPanelProfileFirstLife::onRemovePhoto() +{ + onCommitPhoto(LLUUID::null); + + LLFloater* floaterp = mFloaterTexturePickerHandle.get(); + if (floaterp) + { + floaterp->closeFloater(); + } +} + +void LLPanelProfileFirstLife::onCommitPhoto(const LLUUID& id) +{ + if (mPicture->getImageAssetId() == id) + return; + + if (!saveAgentUserInfoCoro("fl_image_id", id)) + return; + + mPicture->setValue(id); + + mRemovePhoto->setEnabled(id.notNull()); +} + +void LLPanelProfileFirstLife::setDescriptionText(const std::string &text) +{ + mSaveChanges->setEnabled(false); + mDiscardChanges->setEnabled(false); + mHasUnsavedChanges = false; + + mCurrentDescription = text; + mDescriptionEdit->setValue(mCurrentDescription); +} + +void LLPanelProfileFirstLife::onSetDescriptionDirty() +{ + mSaveChanges->setEnabled(true); + mDiscardChanges->setEnabled(true); + mHasUnsavedChanges = true; +} + +void LLPanelProfileFirstLife::onSaveDescriptionChanges() +{ + mCurrentDescription = mDescriptionEdit->getValue().asString(); + saveAgentUserInfoCoro("fl_about_text", mCurrentDescription); + + mSaveChanges->setEnabled(false); + mDiscardChanges->setEnabled(false); + mHasUnsavedChanges = false; +} + +void LLPanelProfileFirstLife::onDiscardDescriptionChanges() +{ + setDescriptionText(mCurrentDescription); +} + +void LLPanelProfileFirstLife::processProperties(void* data, EAvatarProcessorType type) +{ + if (APT_PROPERTIES == type) + { + LLAvatarData* avatar_data = static_cast(data); + if (avatar_data && getAvatarId() == avatar_data->avatar_id) + { + processProperties(avatar_data); + } + } +} + +void LLPanelProfileFirstLife::processProperties(const LLAvatarData* avatar_data) +{ + setDescriptionText(avatar_data->fl_about_text); + + mPicture->setValue(avatar_data->fl_image_id); + + setLoaded(); +} + +void LLPanelProfileFirstLife::resetData() +{ + setDescriptionText(std::string()); + mPicture->setValue(LLUUID::null); + + mUploadPhoto->setVisible(getSelfProfile()); + mChangePhoto->setVisible(getSelfProfile()); + mRemovePhoto->setVisible(getSelfProfile()); + mSaveChanges->setVisible(getSelfProfile()); + mDiscardChanges->setVisible(getSelfProfile()); +} + +void LLPanelProfileFirstLife::setLoaded() +{ + LLPanelProfileTab::setLoaded(); + + if (getSelfProfile()) + { + mDescriptionEdit->setEnabled(true); + mPicture->setEnabled(true); + mRemovePhoto->setEnabled(mPicture->getImageAssetId().notNull()); + } +} + +////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// + +LLPanelProfileNotes::LLPanelProfileNotes() +: LLPanelProfilePropertiesProcessorTab() + , mHasUnsavedChanges(false) +{ + +} + +LLPanelProfileNotes::~LLPanelProfileNotes() +{ +} + +void LLPanelProfileNotes::commitUnsavedChanges() +{ + if (mHasUnsavedChanges) + { + onSaveNotesChanges(); + } +} + +bool LLPanelProfileNotes::postBuild() +{ + mNotesEditor = getChild("notes_edit"); + mSaveChanges = getChild("notes_save_changes"); + mDiscardChanges = getChild("notes_discard_changes"); + + mSaveChanges->setCommitCallback([this](LLUICtrl*, void*) { onSaveNotesChanges(); }, nullptr); + mDiscardChanges->setCommitCallback([this](LLUICtrl*, void*) { onDiscardNotesChanges(); }, nullptr); + mNotesEditor->setKeystrokeCallback([this](LLTextEditor* caller) { onSetNotesDirty(); }); + + return true; +} + +void LLPanelProfileNotes::onOpen(const LLSD& key) +{ + LLPanelProfileTab::onOpen(key); + + resetData(); +} + +void LLPanelProfileNotes::setNotesText(const std::string &text) +{ + mSaveChanges->setEnabled(false); + mDiscardChanges->setEnabled(false); + mHasUnsavedChanges = false; + + mCurrentNotes = text; + mNotesEditor->setValue(mCurrentNotes); +} + +void LLPanelProfileNotes::onSetNotesDirty() +{ + mSaveChanges->setEnabled(true); + mDiscardChanges->setEnabled(true); + mHasUnsavedChanges = true; +} + +void LLPanelProfileNotes::onSaveNotesChanges() +{ + mCurrentNotes = mNotesEditor->getValue().asString(); + saveAgentUserInfoCoro("notes", mCurrentNotes); + + mSaveChanges->setEnabled(false); + mDiscardChanges->setEnabled(false); + mHasUnsavedChanges = false; +} + +void LLPanelProfileNotes::onDiscardNotesChanges() +{ + setNotesText(mCurrentNotes); +} + +void LLPanelProfileNotes::processProperties(void* data, EAvatarProcessorType type) +{ + if (APT_PROPERTIES == type) + { + LLAvatarData* avatar_data = static_cast(data); + if (avatar_data && getAvatarId() == avatar_data->avatar_id) + { + processProperties(avatar_data); + } + } +} + +void LLPanelProfileNotes::processProperties(const LLAvatarData* avatar_data) +{ + setNotesText(avatar_data->notes); + mNotesEditor->setEnabled(true); + setLoaded(); +} + +void LLPanelProfileNotes::resetData() +{ + resetLoading(); + setNotesText(std::string()); +} + + +////////////////////////////////////////////////////////////////////////// +// LLPanelProfile + +LLPanelProfile::LLPanelProfile() + : LLPanelProfileTab() +{ +} + +LLPanelProfile::~LLPanelProfile() +{ +} + +bool LLPanelProfile::postBuild() +{ + return true; +} + +void LLPanelProfile::onTabChange() +{ + LLPanelProfileTab* active_panel = dynamic_cast(mTabContainer->getCurrentPanel()); + if (active_panel) + { + active_panel->updateData(); + } +} + +void LLPanelProfile::onOpen(const LLSD& key) +{ + LLUUID avatar_id = key["id"].asUUID(); + + // Don't reload the same profile + if (getAvatarId() == avatar_id) + { + return; + } + + LLPanelProfileTab::onOpen(avatar_id); + + mTabContainer = getChild("panel_profile_tabs"); + mPanelSecondlife = findChild(PANEL_SECONDLIFE); + mPanelWeb = findChild(PANEL_WEB); + mPanelPicks = findChild(PANEL_PICKS); + mPanelClassifieds = findChild(PANEL_CLASSIFIEDS); + mPanelFirstlife = findChild(PANEL_FIRSTLIFE); + mPanelNotes = findChild(PANEL_NOTES); + + mPanelSecondlife->onOpen(avatar_id); + mPanelWeb->onOpen(avatar_id); + mPanelPicks->onOpen(avatar_id); + mPanelClassifieds->onOpen(avatar_id); + mPanelFirstlife->onOpen(avatar_id); + mPanelNotes->onOpen(avatar_id); + + // Always request the base profile info + resetLoading(); + updateData(); + + // Some tabs only request data when opened + mTabContainer->setCommitCallback(boost::bind(&LLPanelProfile::onTabChange, this)); +} + +void LLPanelProfile::updateData() +{ + LLUUID avatar_id = getAvatarId(); + // Todo: getIsloading functionality needs to be expanded to + // include 'inited' or 'data_provided' state to not rerequest + if (!getStarted() && avatar_id.notNull()) + { + setIsLoading(); + + mPanelSecondlife->setIsLoading(); + mPanelPicks->setIsLoading(); + mPanelFirstlife->setIsLoading(); + mPanelNotes->setIsLoading(); + + LLAvatarPropertiesProcessor::getInstance()->sendAvatarPropertiesRequest(getAvatarId()); + } +} + +void LLPanelProfile::refreshName() +{ + mPanelSecondlife->refreshName(); +} + +void LLPanelProfile::createPick(const LLPickData &data) +{ + mTabContainer->selectTabPanel(mPanelPicks); + mPanelPicks->createPick(data); +} + +void LLPanelProfile::showPick(const LLUUID& pick_id) +{ + if (pick_id.notNull()) + { + mPanelPicks->selectPick(pick_id); + } + mTabContainer->selectTabPanel(mPanelPicks); +} + +bool LLPanelProfile::isPickTabSelected() +{ + return (mTabContainer->getCurrentPanel() == mPanelPicks); +} + +bool LLPanelProfile::isNotesTabSelected() +{ + return (mTabContainer->getCurrentPanel() == mPanelNotes); +} + +bool LLPanelProfile::hasUnsavedChanges() +{ + return mPanelSecondlife->hasUnsavedChanges() + || mPanelPicks->hasUnsavedChanges() + || mPanelClassifieds->hasUnsavedChanges() + || mPanelFirstlife->hasUnsavedChanges() + || mPanelNotes->hasUnsavedChanges(); +} + +bool LLPanelProfile::hasUnpublishedClassifieds() +{ + return mPanelClassifieds->hasNewClassifieds(); +} + +void LLPanelProfile::commitUnsavedChanges() +{ + mPanelSecondlife->commitUnsavedChanges(); + mPanelPicks->commitUnsavedChanges(); + mPanelClassifieds->commitUnsavedChanges(); + mPanelFirstlife->commitUnsavedChanges(); + mPanelNotes->commitUnsavedChanges(); +} + +void LLPanelProfile::showClassified(const LLUUID& classified_id, bool edit) +{ + if (classified_id.notNull()) + { + mPanelClassifieds->selectClassified(classified_id, edit); + } + mTabContainer->selectTabPanel(mPanelClassifieds); +} + +void LLPanelProfile::createClassified() +{ + mPanelClassifieds->createClassified(); + mTabContainer->selectTabPanel(mPanelClassifieds); +} + -- cgit v1.2.3 From b42f9d836b4c0f7fbd4bdae1734021e2a09fdbe8 Mon Sep 17 00:00:00 2001 From: Ansariel Date: Sat, 1 Jun 2024 15:49:26 +0200 Subject: Re-enable a lot of compiler warnings for MSVC and address the C4267 "possible loss of precision" warnings --- indra/newview/llpanelprofile.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'indra/newview/llpanelprofile.cpp') diff --git a/indra/newview/llpanelprofile.cpp b/indra/newview/llpanelprofile.cpp index 579f0941c3..19e2d5de99 100644 --- a/indra/newview/llpanelprofile.cpp +++ b/indra/newview/llpanelprofile.cpp @@ -1430,7 +1430,7 @@ void LLPanelProfileSecondLife::onCommitMenu(const LLSD& userdata) else if (item_name == "copy_user_id") { LLWString wstr = utf8str_to_wstring(getAvatarId().asString()); - LLClipboard::instance().copyToClipboard(wstr, 0, wstr.size()); + LLClipboard::instance().copyToClipboard(wstr, 0, static_cast(wstr.size())); } else if (item_name == "agent_permissions") { @@ -1455,7 +1455,7 @@ void LLPanelProfileSecondLife::onCommitMenu(const LLSD& userdata) { wstr = utf8str_to_wstring(av_name.getUserName()); } - LLClipboard::instance().copyToClipboard(wstr, 0, wstr.size()); + LLClipboard::instance().copyToClipboard(wstr, 0, static_cast(wstr.size())); } else if (item_name == "edit_display_name") { -- cgit v1.2.3 From 1c50229e6e8ceff6ebddff72aa26f39eed3a561c Mon Sep 17 00:00:00 2001 From: Zi Ree <81702435+zi-ree@users.noreply.github.com> Date: Sun, 28 Jul 2024 03:21:34 +0200 Subject: fix misleading indentation compiler warnings Fix several indentation mistakes, some of them trip gcc's misleading indentation warning. --- indra/newview/llpanelprofile.cpp | 48 ++++++++++++++++++++-------------------- 1 file changed, 24 insertions(+), 24 deletions(-) (limited to 'indra/newview/llpanelprofile.cpp') diff --git a/indra/newview/llpanelprofile.cpp b/indra/newview/llpanelprofile.cpp index fcf0757073..8f44b28ebe 100644 --- a/indra/newview/llpanelprofile.cpp +++ b/indra/newview/llpanelprofile.cpp @@ -1020,7 +1020,7 @@ void LLPanelProfileSecondLife::fillCommonData(const LLAvatarData* avatar_data) setDescriptionText(avatar_data->about_text); - mSecondLifePic->setValue(avatar_data->image_id); + mSecondLifePic->setValue(avatar_data->image_id); if (getSelfProfile()) { @@ -1168,10 +1168,10 @@ void LLPanelProfileSecondLife::fillAgeData(const LLAvatarData* avatar_data) } else { - std::string register_date = getString("age_format"); - LLSD args_age; + std::string register_date = getString("age_format"); + LLSD args_age; args_age["[AGE]"] = LLDateUtil::ageFromDate(avatar_data->born_on, LLDate::now()); - LLStringUtil::format(register_date, args_age); + LLStringUtil::format(register_date, args_age); userAgeCtrl->setValue(register_date); } @@ -1614,12 +1614,12 @@ void LLPanelProfileSecondLife::onShowInSearchCallback() if (value == mAllowPublish) return; - mAllowPublish = value; + mAllowPublish = value; saveAgentUserInfoCoro("allow_publish", value); - } +} void LLPanelProfileSecondLife::onHideAgeCallback() - { +{ bool value = mHideAgeCombo->getValue().asInteger(); if (value == mHideAge) return; @@ -1768,35 +1768,35 @@ void LLPanelProfileSecondLife::onCommitProfileImage(const LLUUID& id) if (mSecondLifePic->getImageAssetId() == id) return; - std::function callback = [id](bool result) + std::function callback = [id](bool result) + { + if (result) { - if (result) - { - LLAvatarIconIDCache::getInstance()->add(gAgentID, id); + LLAvatarIconIDCache::getInstance()->add(gAgentID, id); // Should trigger callbacks in icon controls (or request Legacy) - LLAvatarPropertiesProcessor::getInstance()->sendAvatarPropertiesRequest(gAgentID); - } - }; + LLAvatarPropertiesProcessor::getInstance()->sendAvatarPropertiesRequest(gAgentID); + } + }; if (!saveAgentUserInfoCoro("sl_image_id", id, callback)) return; mSecondLifePic->setValue(id); - LLFloater *floater = mFloaterProfileTextureHandle.get(); - if (floater) - { - LLFloaterProfileTexture * texture_view = dynamic_cast(floater); + LLFloater *floater = mFloaterProfileTextureHandle.get(); + if (floater) + { + LLFloaterProfileTexture * texture_view = dynamic_cast(floater); if (id == LLUUID::null) - { - texture_view->resetAsset(); - } - else - { + { + texture_view->resetAsset(); + } + else + { texture_view->loadAsset(id); - } } } +} ////////////////////////////////////////////////////////////////////////// // LLPanelProfileWeb -- cgit v1.2.3