diff options
| author | Mnikolenko Productengine <mnikolenko@productengine.com> | 2025-10-30 16:59:51 +0200 |
|---|---|---|
| committer | Mnikolenko Productengine <mnikolenko@productengine.com> | 2025-10-30 16:59:51 +0200 |
| commit | cf048cf9c3ebd9ca8ee1e606b69bc459b62ed1c5 (patch) | |
| tree | 9864a2073a056ee6fd6b7391a2c39b885bb09363 /indra/newview | |
| parent | 21e9b38f06e187414d30c12c8c69ebf7b4e4e636 (diff) | |
#4013 Update voice moderator options; show notifications when muted; add stub code for info request
Diffstat (limited to 'indra/newview')
| -rw-r--r-- | indra/newview/llfloaterimcontainer.cpp | 35 | ||||
| -rw-r--r-- | indra/newview/llfloaterimcontainer.h | 1 | ||||
| -rw-r--r-- | indra/newview/llnearbyvoicemoderation.cpp | 113 | ||||
| -rw-r--r-- | indra/newview/llnearbyvoicemoderation.h | 26 | ||||
| -rwxr-xr-x | indra/newview/llviewerregion.cpp | 1 | ||||
| -rw-r--r-- | indra/newview/llvoiceclient.cpp | 4 | ||||
| -rw-r--r-- | indra/newview/llvoicewebrtc.cpp | 8 | ||||
| -rw-r--r-- | indra/newview/skins/default/xui/en/notifications.xml | 23 |
8 files changed, 165 insertions, 46 deletions
diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp index c25fbdcc51..ac8234bf24 100644 --- a/indra/newview/llfloaterimcontainer.cpp +++ b/indra/newview/llfloaterimcontainer.cpp @@ -92,6 +92,7 @@ LLFloaterIMContainer::LLFloaterIMContainer(const LLSD& seed, const Params& param mAutoResize = false; LLTransientFloaterMgr::getInstance()->addControlView(LLTransientFloaterMgr::IM, this); + LLNearbyVoiceModeration::getInstance(); } LLFloaterIMContainer::~LLFloaterIMContainer() @@ -543,7 +544,7 @@ void LLFloaterIMContainer::idleUpdate() dynamic_cast<LLConversationItemParticipant*>((*current_participant_model).get()); if (participant_model) { - participant_model->setModeratorOptionsVisible(isNearbyChatModerator()); + participant_model->setModeratorOptionsVisible(LLNearbyVoiceModeration::getInstance()->isNearbyChatModerator()); } current_participant_model++; @@ -2037,7 +2038,7 @@ LLConversationViewParticipant* LLFloaterIMContainer::createConversationViewParti bool LLFloaterIMContainer::enableModerateContextMenuItem(const std::string& userdata, bool is_self) { - if (isNearbyChatModerator() && isNearbyChatSpeakerSelected()) + if (LLNearbyVoiceModeration::getInstance()->isNearbyChatModerator() && isNearbyChatSpeakerSelected()) { // Determine here which actions are allowed if ("can_moderate_voice" == userdata) @@ -2046,7 +2047,7 @@ bool LLFloaterIMContainer::enableModerateContextMenuItem(const std::string& user } else if (("can_mute" == userdata)) { - return true; + return !is_self; } else if ("can_unmute" == userdata) { @@ -2199,30 +2200,12 @@ void LLFloaterIMContainer::moderateVoice(const std::string& command, const LLUUI { if ("selected" == command) { - // Toggle the voice icon display - LLAvatarActions::toggleMuteVoice(userID); - // Request a mute/unmute using a capability request via the simulator - const bool mute_state = LLAvatarActions::isVoiceMuted(userID); - LLNearbyVoiceModeration::getInstance()->requestMuteIndividual(userID, mute_state); + LLNearbyVoiceModeration::getInstance()->requestMuteIndividual(userID, !isMuted(userID)); } else if ("mute_all" == command) { - // TODO: the SpatialVoiceModerationRequest has an mute_all/unmute_all - // verb but we do not have an equivalent of LLAvatarActions::toggleMuteVoice(userID); - // to visually mute all the speaker icons in the conversation floater - - // Mute visually too - conversations_widgets_map::const_iterator iter = mConversationsWidgets.begin(); - conversations_widgets_map::const_iterator end = mConversationsWidgets.end(); - const LLUUID * conversation_uuidp = NULL; - while(iter != end) - { - const LLUUID id = (*iter).first; - ++iter; - } - // Send the mute_all request to the server const bool mute_state = true; LLNearbyVoiceModeration::getInstance()->requestMuteAll(mute_state); @@ -2230,8 +2213,6 @@ void LLFloaterIMContainer::moderateVoice(const std::string& command, const LLUUI else if ("unmute_all" == command) { - // TODO: same idea as "mute_all" above - // Send the unmute_all request to the server const bool mute_state = false; LLNearbyVoiceModeration::getInstance()->requestMuteAll(mute_state); @@ -2381,12 +2362,6 @@ bool LLFloaterIMContainer::isNearbyChatSpeakerSelected() return conversation_uuidp->isNull(); } -bool LLFloaterIMContainer::isNearbyChatModerator() -{ - // TODO: Need a better heurestic for determining if this person is a moderator :) - return true; -} - void LLFloaterIMContainer::toggleAllowTextChat(const LLUUID& participant_uuid) { LLIMSpeakerMgr * speaker_managerp = dynamic_cast<LLIMSpeakerMgr*>(getSpeakerMgrForSelectedParticipant()); diff --git a/indra/newview/llfloaterimcontainer.h b/indra/newview/llfloaterimcontainer.h index c91093c107..9f1690a9b9 100644 --- a/indra/newview/llfloaterimcontainer.h +++ b/indra/newview/llfloaterimcontainer.h @@ -179,7 +179,6 @@ private: void openNearbyChat(); bool isParticipantListExpanded(); bool isNearbyChatSpeakerSelected(); - bool isNearbyChatModerator(); void idleUpdate(); // for convenience (self) from static idle void idleProcessEvents(); diff --git a/indra/newview/llnearbyvoicemoderation.cpp b/indra/newview/llnearbyvoicemoderation.cpp index 5ae8feba08..ec0e1c0431 100644 --- a/indra/newview/llnearbyvoicemoderation.cpp +++ b/indra/newview/llnearbyvoicemoderation.cpp @@ -26,12 +26,29 @@ #include "llviewerprecompiledheaders.h" #include "llagent.h" +#include "llnotificationsutil.h" #include "llviewerregion.h" #include "llvoavatar.h" +#include "llvoiceclient.h" #include "llviewerobjectlist.h" #include "llnearbyvoicemoderation.h" +LLNearbyVoiceModeration::LLNearbyVoiceModeration() +{ + // TODO: default to false, when appropriate info cap is added + mIsNearbyChatModerator = true; + mParcelCallbackConnection = gAgent.addParcelChangedCallback([this]() { updateModeratorStatus(); }); +} + +LLNearbyVoiceModeration::~LLNearbyVoiceModeration() +{ + if (mParcelCallbackConnection.connected()) + { + mParcelCallbackConnection.disconnect(); + } +} + LLVOAvatar* LLNearbyVoiceModeration::getVOAvatarFromId(const LLUUID& agent_id) { LLViewerObject *obj = gObjectList.findObject(agent_id); @@ -54,18 +71,12 @@ const std::string LLNearbyVoiceModeration::getCapUrlFromRegion(LLViewerRegion* r { if (! region || ! region->capabilitiesReceived()) { - // TODO: Retry if fails since the capabilities may not have been received - // if this is called early into a region entry - LL_INFOS() << "Region or region capabilities unavailable." << LL_ENDL; return std::string(); } - LL_INFOS() << "Capabilities for region " << region->getName() << " received." << LL_ENDL; std::string url = region->getCapability("SpatialVoiceModerationRequest"); if (url.empty()) { - // TODO: Retry if fails since URL may not have not be available - // if this is called early into a region entry LL_INFOS() << "Capability URL for region " << region->getName() << " is empty" << LL_ENDL; return std::string(); } @@ -139,3 +150,93 @@ void LLNearbyVoiceModeration::requestMuteAll(bool mute) failure_msg); } } + +void LLNearbyVoiceModeration::setMutedInfo(const std::string& channelID, bool mute) +{ + auto it = mChannelMuteMap.find(channelID); + if (it == mChannelMuteMap.end()) + { + if (mute) + { + // Channel is new and being muted + showMutedNotification(true); + } + mChannelMuteMap[channelID] = mute; + } + else + { + if (it->second != mute) + { + // Flag changed + showMutedNotification(mute); + it->second = mute; + } + } +} + +void LLNearbyVoiceModeration::showNotificationIfNeeded() +{ + if (LLVoiceClient::getInstance()->inProximalChannel() && + LLVoiceClient::getInstance()->getIsModeratorMuted(gAgentID)) + { + showMutedNotification(true); + } +} + +void LLNearbyVoiceModeration::showMutedNotification(bool is_muted) +{ + // Check if the current voice channel is nearby chat + if (LLVoiceClient::getInstance()->inProximalChannel()) + { + LLNotificationsUtil::add(is_muted ? "NearbyVoiceMutedByModerator" : "NearbyVoiceUnmutedByModerator"); + } +} + +void LLNearbyVoiceModeration::updateModeratorStatus() +{ + LL_WARNS() << "Request moderator status info" << LL_ENDL; + // TODO: Uncomment and set correct capability name, when appropriate info cap is added + /* + if (LLViewerRegion* region = gAgent.getRegion()) + { + + std::string url = region->getCapability("SpatialVoiceModerationInfoRequest"); + if (!url.empty()) + { + LLCoros::instance().launch("getModeratorStatusCoro", [url]() { getModeratorStatusCoro(url); }); + } + } + */ +} + +void LLNearbyVoiceModeration::getModeratorStatusCoro(std::string cap_url) +{ + LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID); + LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("getModeratorStatusCoro", httpPolicy)); + LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest); + LLCore::HttpOptions::ptr_t httpOpts(new LLCore::HttpOptions); + LLCore::HttpHeaders::ptr_t httpHeaders; + + httpOpts->setFollowRedirects(true); + + LLSD result = httpAdapter->getAndSuspend(httpRequest, cap_url, httpOpts, httpHeaders); + + LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS]; + LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults); + + if (!status) + { + LL_WARNS() << "Failed to get nearby voice moderator info" << LL_ENDL; + return; + } + else if (!result["success"].asBoolean()) + { + LL_WARNS() << "Failed to get nearby voice moderator info: " << result["message"] << LL_ENDL; + return; + } + + // TODO: update the field, when appropriate info cap is added + bool is_moderator = result["moderator"].asBoolean(); + LLNearbyVoiceModeration::getInstance()->setNearbyChatModerator(is_moderator); +} + diff --git a/indra/newview/llnearbyvoicemoderation.h b/indra/newview/llnearbyvoicemoderation.h index 8a1ca5af6b..21d185db54 100644 --- a/indra/newview/llnearbyvoicemoderation.h +++ b/indra/newview/llnearbyvoicemoderation.h @@ -27,19 +27,29 @@ class LLVOAvatar; -class LLNearbyVoiceModeration : - public LLSingleton <LLNearbyVoiceModeration> { - LLSINGLETON(LLNearbyVoiceModeration) { - }; - - ~LLNearbyVoiceModeration() { - }; +class LLNearbyVoiceModeration : public LLSingleton <LLNearbyVoiceModeration> { + LLSINGLETON(LLNearbyVoiceModeration); + ~LLNearbyVoiceModeration(); public: - LLVOAvatar* getVOAvatarFromId(const LLUUID& id); void requestMuteIndividual(const LLUUID& userID, bool mute); void requestMuteAll(bool mute); + void setMutedInfo(const std::string& channelID, bool mute); + void showMutedNotification(bool is_muted); + void showNotificationIfNeeded(); + + void updateModeratorStatus(); + static void getModeratorStatusCoro(std::string cap_url); + + bool isNearbyChatModerator() { return mIsNearbyChatModerator; }; + void setNearbyChatModerator(bool moderator) { mIsNearbyChatModerator = moderator; } + private: + LLVOAvatar* getVOAvatarFromId(const LLUUID& id); const std::string getCapUrlFromRegion(LLViewerRegion* region); + + boost::signals2::connection mParcelCallbackConnection; + std::map<std::string, bool> mChannelMuteMap; + bool mIsNearbyChatModerator; }; diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp index a085bc4d91..fa60c36834 100755 --- a/indra/newview/llviewerregion.cpp +++ b/indra/newview/llviewerregion.cpp @@ -3300,6 +3300,7 @@ void LLViewerRegionImpl::buildCapabilityNames(LLSD& capabilityNames) capabilityNames.append("SetDisplayName"); capabilityNames.append("SimConsoleAsync"); capabilityNames.append("SimulatorFeatures"); + capabilityNames.append("SpatialVoiceModerationRequest"); capabilityNames.append("StartGroupProposal"); capabilityNames.append("TerrainNavMeshProperties"); capabilityNames.append("TextureStats"); diff --git a/indra/newview/llvoiceclient.cpp b/indra/newview/llvoiceclient.cpp index 71a9e71a9f..5a2ef248ba 100644 --- a/indra/newview/llvoiceclient.cpp +++ b/indra/newview/llvoiceclient.cpp @@ -39,6 +39,7 @@ #include "llagent.h" #include "lltrans.h" #include "lluiusage.h" +#include "llnearbyvoicemoderation.h" const F32 LLVoiceClient::OVERDRIVEN_POWER_LEVEL = 0.7f; @@ -712,6 +713,9 @@ bool LLVoiceClient::getPTTIsToggle() void LLVoiceClient::inputUserControlState(bool down) { + if (down && !getUserPTTState()) + LLNearbyVoiceModeration::getInstance()->showNotificationIfNeeded(); + if(mPTTIsToggle) { if(down) // toggle open-mic state on 'down' diff --git a/indra/newview/llvoicewebrtc.cpp b/indra/newview/llvoicewebrtc.cpp index 93f8f0d14a..1d78ca002a 100644 --- a/indra/newview/llvoicewebrtc.cpp +++ b/indra/newview/llvoicewebrtc.cpp @@ -65,6 +65,7 @@ #include "llviewernetwork.h" #include "llnotificationsutil.h" +#include "llnearbyvoicemoderation.h" #include "llcorehttputil.h" #include "lleventfilter.h" @@ -3194,14 +3195,19 @@ void LLVoiceWebRTCConnection::OnDataReceivedImpl(const std::string &data, bool b participant->mIsSpeaking = participant_obj["v"].as_bool(); } + // Currently, viewer doesn't receive this info when the user is muted in Nearby chat, + // but it *does* receive it when muted in Group chat. A server-side change is required. if (participant_obj.contains("m") && participant_obj["m"].is_bool()) { participant->mIsModeratorMuted = participant_obj["m"].as_bool(); + if (isSpatial() && (gAgentID == agent_id)) + { + LLNearbyVoiceModeration::getInstance()->setMutedInfo(mChannelID, participant->mIsModeratorMuted); + } } } } } - // tell the simulator to set the mute and volume data for this // participant, if there are any updates. boost::json::object root; diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml index dbd513afe8..3f9a2ba13e 100644 --- a/indra/newview/skins/default/xui/en/notifications.xml +++ b/indra/newview/skins/default/xui/en/notifications.xml @@ -9193,6 +9193,29 @@ Your voice has been muted by moderator. </notification> <notification + icon="alertmodal.tga" + name="NearbyVoiceMutedByModerator" + type="alertmodal"> + The moderator has muted your voice chat. +People in this location will not hear you if you speak. + <tag>voice</tag> + <usetemplate + name="okbutton" + yestext="OK"/> + </notification> + + <notification + icon="alertmodal.tga" + name="NearbyVoiceUnmutedByModerator" + type="alertmodal"> + Your voice chat can now be heard by people in this location. + <tag>voice</tag> + <usetemplate + name="okbutton" + yestext="OK"/> + </notification> + + <notification icon="alertmodal.tga" name="FailedToGetBenefits" type="alertmodal"> |
