Sync to fix using gMessageSystem when it may not have the right message

This commit is contained in:
Liru Færs
2020-04-07 02:54:31 -04:00
parent 79d938a4f4
commit b86eae026b
5 changed files with 102 additions and 89 deletions

View File

@@ -801,7 +801,7 @@ void LLFloaterIMPanel::addHistoryLine(const std::string &utf8msg, LLColor4 incol
// Now we're adding the actual line of text, so erase the
// "Foo is typing..." text segment, and the optional timestamp
// if it was present. JC
removeTypingIndicator(NULL);
removeTypingIndicator(source);
// Actually add the line
bool prepend_newline = true;
@@ -1458,7 +1458,7 @@ void LLFloaterIMPanel::onSendMsg()
bool other_was_typing = mOtherTyping;
addHistoryLine(utf8_text, gSavedSettings.getColor("UserChatColor"), true, gAgentID, name);
if (other_was_typing) addTypingIndicator(mOtherTypingName);
if (other_was_typing) addTypingIndicator(mOtherParticipantUUID);
}
}
else
@@ -1588,53 +1588,84 @@ void LLFloaterIMPanel::sendTypingState(bool typing)
}
void LLFloaterIMPanel::processIMTyping(const LLIMInfo* im_info, bool typing)
void LLFloaterIMPanel::processIMTyping(const LLUUID& from_id, BOOL typing)
{
if (typing)
{
// other user started typing
std::string name;
if (!LLAvatarNameCache::getNSName(im_info->mFromID, name)) name = im_info->mName;
addTypingIndicator(name);
addTypingIndicator(from_id);
}
else
{
// other user stopped typing
removeTypingIndicator(im_info);
removeTypingIndicator(from_id);
}
}
void LLFloaterIMPanel::addTypingIndicator(const std::string &name)
void LLFloaterIMPanel::addTypingIndicator(const LLUUID& from_id)
{
// we may have lost a "stop-typing" packet, don't add it twice
if (!mOtherTyping)
// Singu TODO: Actually implement this?
/* Operation of "<name> is typing" state machine:
Not Typing state:
User types in P2P IM chat ... Send Start Typing, save Started time,
start Idle Timer (N seconds) go to Typing state
Typing State:
User enters a non-return character: if Now - Started > ME_TYPING_TIMEOUT, send
Start Typing, restart Idle Timer
User enters a return character: stop Idle Timer, send IM and Stop
Typing, go to Not Typing state
Idle Timer expires: send Stop Typing, go to Not Typing state
The recipient has a complementary state machine in which a Start Typing
that is not followed by either an IM or another Start Typing within OTHER_TYPING_TIMEOUT
seconds switches the sender out of typing state.
This has the nice quality of being self-healing for lost start/stop
messages while adding messages only for the (relatively rare) case of a
user who types a very long message (one that takes more than ME_TYPING_TIMEOUT seconds
to type).
Note: OTHER_TYPING_TIMEOUT must be > ME_TYPING_TIMEOUT for proper operation of the state machine
*/
// We may have lost a "stop-typing" packet, don't add it twice
if (from_id.notNull() && !mOtherTyping)
{
mOtherTyping = true;
// Save im_info so that removeTypingIndicator can be properly called because a timeout has occurred
LLAvatarNameCache::getNSName(from_id, mOtherTypingName);
mTypingLineStartIndex = mHistoryEditor->getWText().length();
LLUIString typing_start = sTypingStartString;
typing_start.setArg("[NAME]", name);
typing_start.setArg("[NAME]", mOtherTypingName);
addHistoryLine(typing_start, gSavedSettings.getColor4("SystemChatColor"), false);
mOtherTypingName = name;
mOtherTyping = true;
// Update speaker
LLIMSpeakerMgr* speaker_mgr = mSpeakers;
if ( speaker_mgr )
{
speaker_mgr->setSpeakerTyping(from_id, TRUE);
}
}
// MBW -- XXX -- merge from release broke this (argument to this function changed from an LLIMInfo to a name)
// Richard will fix.
// mSpeakers->setSpeakerTyping(im_info->mFromID, TRUE);
}
void LLFloaterIMPanel::removeTypingIndicator(const LLIMInfo* im_info)
void LLFloaterIMPanel::removeTypingIndicator(const LLUUID& from_id)
{
if (mOtherTyping)
{
// Must do this first, otherwise addHistoryLine calls us again.
mOtherTyping = false;
S32 chars_to_remove = mHistoryEditor->getWText().length() - mTypingLineStartIndex;
mHistoryEditor->removeTextFromEnd(chars_to_remove);
if (im_info)
if (from_id.notNull())
{
mSpeakers->setSpeakerTyping(im_info->mFromID, FALSE);
mSpeakers->setSpeakerTyping(from_id, FALSE);
}
}
}

View File

@@ -126,7 +126,7 @@ public:
void sessionInitReplyReceived(const LLUUID& im_session_id);
// Handle other participant in the session typing.
void processIMTyping(const LLIMInfo* im_info, bool typing);
void processIMTyping(const LLUUID& from_id, BOOL typing);
static void chatFromLogFile(LLLogChat::ELogLineType type, std::string line, void* userdata);
//show error statuses to the user
@@ -177,10 +177,10 @@ private:
void setTyping(bool typing);
// Add the "User is typing..." indicator.
void addTypingIndicator(const std::string &name);
void addTypingIndicator(const LLUUID& from_id);
// Remove the "User is typing..." indicator.
void removeTypingIndicator(const LLIMInfo* im_info);
void removeTypingIndicator(const LLUUID& from_id = LLUUID::null);
void sendTypingState(bool typing);

View File

@@ -641,8 +641,7 @@ void LLIMProcessing::processNewMessage(const LLUUID& from_id,
{
RlvUtil::sendBusyMessage(from_id, RlvStrings::getVersion(), session_id);
// We won't receive a typing stop message, so do that manually (see comment at the end of LLFloaterIMPanel::sendMsg)
LLPointer<LLIMInfo> im_info = new LLIMInfo(gMessageSystem);
gIMMgr->processIMTypingStop(im_info);
gIMMgr->processIMTypingStop(from_id, dialog);
}
// [/RLVa:KB]
else if (offline == IM_ONLINE
@@ -918,16 +917,15 @@ void LLIMProcessing::processNewMessage(const LLUUID& from_id,
autoresponder_finish(show_autoresponded, session_id, from_id, name, itemid, is_muted);
}
}
LLPointer<LLIMInfo> im_info = new LLIMInfo(gMessageSystem);
gIMMgr->processIMTypingStart(im_info);
gIMMgr->processIMTypingStart(from_id, dialog);
script_msg_api(from_id.asString() + ", 4");
}
break;
case IM_TYPING_STOP:
{
LLPointer<LLIMInfo> im_info = new LLIMInfo(gMessageSystem);
gIMMgr->processIMTypingStop(im_info);
gIMMgr->processIMTypingStop(from_id, dialog);
script_msg_api(from_id.asString() + ", 5");
}
break;

View File

@@ -1138,23 +1138,23 @@ void LLIMMgr::noteMutedUsers(LLFloaterIMPanel* floater,
}
}
void LLIMMgr::processIMTypingStart(const LLIMInfo* im_info)
void LLIMMgr::processIMTypingStart(const LLUUID& from_id, const EInstantMessage im_type)
{
processIMTypingCore(im_info, TRUE);
processIMTypingCore(from_id, im_type, TRUE);
}
void LLIMMgr::processIMTypingStop(const LLIMInfo* im_info)
void LLIMMgr::processIMTypingStop(const LLUUID& from_id, const EInstantMessage im_type)
{
processIMTypingCore(im_info, FALSE);
processIMTypingCore(from_id, im_type, FALSE);
}
void LLIMMgr::processIMTypingCore(const LLIMInfo* im_info, BOOL typing)
void LLIMMgr::processIMTypingCore(const LLUUID& from_id, const EInstantMessage im_type, BOOL typing)
{
LLUUID session_id = computeSessionID(im_info->mIMType, im_info->mFromID);
LLFloaterIMPanel* floater = findFloaterBySession(session_id);
if (floater)
LLUUID session_id = computeSessionID(im_type, from_id);
LLFloaterIMPanel* im_floater = findFloaterBySession(session_id);
if (im_floater)
{
floater->processIMTyping(im_info, typing);
im_floater->processIMTyping(from_id, typing);
}
}
@@ -1275,10 +1275,10 @@ LLFloaterChatterBox* LLIMMgr::getFloater()
return LLFloaterChatterBox::getInstance(LLSD());
}
class LLViewerChatterBoxSessionStartReply : public LLHTTPNode
class LLViewerChatterBoxSessionStartReply final : public LLHTTPNode
{
public:
virtual void describe(Description& desc) const
void describe(Description& desc) const override
{
desc.shortInfo("Used for receiving a reply to a request to initialize an ChatterBox session");
desc.postAPI();
@@ -1287,18 +1287,15 @@ public:
desc.source(__FILE__, __LINE__);
}
virtual void post(ResponsePtr response,
void post(ResponsePtr response,
const LLSD& context,
const LLSD& input) const
const LLSD& input) const override
{
LLSD body;
LLUUID temp_session_id;
LLUUID session_id;
bool success;
body = input["body"];
success = body["success"].asBoolean();
temp_session_id = body["temp_session_id"].asUUID();
LLSD body = input["body"];
bool success = body["success"].asBoolean();
LLUUID temp_session_id = body["temp_session_id"].asUUID();
if ( success )
{
@@ -1336,10 +1333,10 @@ public:
}
};
class LLViewerChatterBoxSessionEventReply : public LLHTTPNode
class LLViewerChatterBoxSessionEventReply final : public LLHTTPNode
{
public:
virtual void describe(Description& desc) const
void describe(Description& desc) const override
{
desc.shortInfo("Used for receiving a reply to a ChatterBox session event");
desc.postAPI();
@@ -1348,24 +1345,18 @@ public:
desc.source(__FILE__, __LINE__);
}
virtual void post(ResponsePtr response,
void post(ResponsePtr response,
const LLSD& context,
const LLSD& input) const
const LLSD& input) const override
{
LLUUID session_id;
bool success;
LLSD body = input["body"];
success = body["success"].asBoolean();
session_id = body["session_id"].asUUID();
bool success = body["success"].asBoolean();
LLUUID session_id = body["session_id"].asUUID();
if ( !success )
{
//throw an error dialog
LLFloaterIMPanel* floater =
gIMMgr->findFloaterBySession(session_id);
if (floater)
if (auto* floater = gIMMgr->findFloaterBySession(session_id))
{
floater->showSessionEventError(
body["event"].asString(),
@@ -1378,46 +1369,40 @@ public:
class LLViewerForceCloseChatterBoxSession: public LLHTTPNode
{
public:
virtual void post(ResponsePtr response,
void post(ResponsePtr response,
const LLSD& context,
const LLSD& input) const
const LLSD& input) const override
{
LLUUID session_id;
std::string reason;
LLUUID session_id = input["body"]["session_id"].asUUID();
std::string reason = input["body"]["reason"].asString();
session_id = input["body"]["session_id"].asUUID();
reason = input["body"]["reason"].asString();
LLFloaterIMPanel* floater =
gIMMgr ->findFloaterBySession(session_id);
if ( floater )
if (auto* floater = gIMMgr ->findFloaterBySession(session_id))
{
floater->showSessionForceClose(reason);
}
}
};
class LLViewerChatterBoxSessionAgentListUpdates : public LLHTTPNode
class LLViewerChatterBoxSessionAgentListUpdates final : public LLHTTPNode
{
public:
virtual void post(
void post(
ResponsePtr responder,
const LLSD& context,
const LLSD& input) const
const LLSD& input) const override
{
const LLUUID& session_id = input["body"]["session_id"].asUUID();
gIMMgr->processAgentListUpdates(session_id, input["body"]);
}
};
class LLViewerChatterBoxSessionUpdate : public LLHTTPNode
class LLViewerChatterBoxSessionUpdate final : public LLHTTPNode
{
public:
virtual void post(
void post(
ResponsePtr responder,
const LLSD& context,
const LLSD& input) const
const LLSD& input) const override
{
LLUUID session_id = input["body"]["session_id"].asUUID();
LLFloaterIMPanel* im_floater = gIMMgr->findFloaterBySession(session_id);
@@ -1445,14 +1430,14 @@ void leave_group_chat(const LLUUID& from_id, const LLUUID& session_id)
gIMMgr->removeSession(session_id);
}
class LLViewerChatterBoxInvitation : public LLHTTPNode
class LLViewerChatterBoxInvitation final : public LLHTTPNode
{
public:
virtual void post(
void post(
ResponsePtr response,
const LLSD& context,
const LLSD& input) const
const LLSD& input) const override
{
//for backwards compatiblity reasons...we need to still
//check for 'text' or 'voice' invitations...bleh
@@ -1582,10 +1567,9 @@ public:
LLFloaterChat::addChat(chat, TRUE, is_this_agent);
//K now we want to accept the invitation
std::string url = gAgent.getRegion()->getCapability(
"ChatSessionRequest");
std::string url = gAgent.getRegionCapability("ChatSessionRequest");
if ( url != "" )
if (!url.empty())
{
LLSD data;
data["method"] = "accept invitation";

View File

@@ -42,7 +42,7 @@
class LLFloaterChatterBox;
class LLFloaterIMPanel;
class LLIMMgr : public LLSingleton<LLIMMgr>
class LLIMMgr final : public LLSingleton<LLIMMgr>
{
public:
enum EInvitationType
@@ -121,8 +121,8 @@ public:
void updateFloaterSessionID(const LLUUID& old_session_id,
const LLUUID& new_session_id);
void processIMTypingStart(const LLIMInfo* im_info);
void processIMTypingStop(const LLIMInfo* im_info);
void processIMTypingStart(const LLUUID& from_id, const EInstantMessage im_type);
void processIMTypingStop(const LLUUID& from_id, const EInstantMessage im_type);
void clearNewIMNotification();
@@ -209,7 +209,7 @@ private:
void noteOfflineUsers(LLFloaterIMPanel* panel, const uuid_vec_t& ids);
void noteMutedUsers(LLFloaterIMPanel* panel, const uuid_vec_t& ids);
void processIMTypingCore(const LLIMInfo* im_info, BOOL typing);
void processIMTypingCore(const LLUUID& from_id, const EInstantMessage im_type, BOOL typing);
private:
std::set<LLHandle<LLFloater> > mFloaters;