Sync to fix using gMessageSystem when it may not have the right message
This commit is contained in:
@@ -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
|
// Now we're adding the actual line of text, so erase the
|
||||||
// "Foo is typing..." text segment, and the optional timestamp
|
// "Foo is typing..." text segment, and the optional timestamp
|
||||||
// if it was present. JC
|
// if it was present. JC
|
||||||
removeTypingIndicator(NULL);
|
removeTypingIndicator(source);
|
||||||
|
|
||||||
// Actually add the line
|
// Actually add the line
|
||||||
bool prepend_newline = true;
|
bool prepend_newline = true;
|
||||||
@@ -1458,7 +1458,7 @@ void LLFloaterIMPanel::onSendMsg()
|
|||||||
|
|
||||||
bool other_was_typing = mOtherTyping;
|
bool other_was_typing = mOtherTyping;
|
||||||
addHistoryLine(utf8_text, gSavedSettings.getColor("UserChatColor"), true, gAgentID, name);
|
addHistoryLine(utf8_text, gSavedSettings.getColor("UserChatColor"), true, gAgentID, name);
|
||||||
if (other_was_typing) addTypingIndicator(mOtherTypingName);
|
if (other_was_typing) addTypingIndicator(mOtherParticipantUUID);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
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)
|
if (typing)
|
||||||
{
|
{
|
||||||
// other user started typing
|
// other user started typing
|
||||||
std::string name;
|
addTypingIndicator(from_id);
|
||||||
if (!LLAvatarNameCache::getNSName(im_info->mFromID, name)) name = im_info->mName;
|
|
||||||
addTypingIndicator(name);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// other user stopped typing
|
// 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
|
// Singu TODO: Actually implement this?
|
||||||
if (!mOtherTyping)
|
/* 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();
|
mTypingLineStartIndex = mHistoryEditor->getWText().length();
|
||||||
LLUIString typing_start = sTypingStartString;
|
LLUIString typing_start = sTypingStartString;
|
||||||
typing_start.setArg("[NAME]", name);
|
typing_start.setArg("[NAME]", mOtherTypingName);
|
||||||
addHistoryLine(typing_start, gSavedSettings.getColor4("SystemChatColor"), false);
|
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 LLUUID& from_id)
|
||||||
void LLFloaterIMPanel::removeTypingIndicator(const LLIMInfo* im_info)
|
|
||||||
{
|
{
|
||||||
if (mOtherTyping)
|
if (mOtherTyping)
|
||||||
{
|
{
|
||||||
// Must do this first, otherwise addHistoryLine calls us again.
|
|
||||||
mOtherTyping = false;
|
mOtherTyping = false;
|
||||||
|
|
||||||
S32 chars_to_remove = mHistoryEditor->getWText().length() - mTypingLineStartIndex;
|
S32 chars_to_remove = mHistoryEditor->getWText().length() - mTypingLineStartIndex;
|
||||||
mHistoryEditor->removeTextFromEnd(chars_to_remove);
|
mHistoryEditor->removeTextFromEnd(chars_to_remove);
|
||||||
if (im_info)
|
|
||||||
|
if (from_id.notNull())
|
||||||
{
|
{
|
||||||
mSpeakers->setSpeakerTyping(im_info->mFromID, FALSE);
|
mSpeakers->setSpeakerTyping(from_id, FALSE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -126,7 +126,7 @@ public:
|
|||||||
void sessionInitReplyReceived(const LLUUID& im_session_id);
|
void sessionInitReplyReceived(const LLUUID& im_session_id);
|
||||||
|
|
||||||
// Handle other participant in the session typing.
|
// 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);
|
static void chatFromLogFile(LLLogChat::ELogLineType type, std::string line, void* userdata);
|
||||||
|
|
||||||
//show error statuses to the user
|
//show error statuses to the user
|
||||||
@@ -177,10 +177,10 @@ private:
|
|||||||
void setTyping(bool typing);
|
void setTyping(bool typing);
|
||||||
|
|
||||||
// Add the "User is typing..." indicator.
|
// Add the "User is typing..." indicator.
|
||||||
void addTypingIndicator(const std::string &name);
|
void addTypingIndicator(const LLUUID& from_id);
|
||||||
|
|
||||||
// Remove the "User is typing..." indicator.
|
// Remove the "User is typing..." indicator.
|
||||||
void removeTypingIndicator(const LLIMInfo* im_info);
|
void removeTypingIndicator(const LLUUID& from_id = LLUUID::null);
|
||||||
|
|
||||||
void sendTypingState(bool typing);
|
void sendTypingState(bool typing);
|
||||||
|
|
||||||
|
|||||||
@@ -641,8 +641,7 @@ void LLIMProcessing::processNewMessage(const LLUUID& from_id,
|
|||||||
{
|
{
|
||||||
RlvUtil::sendBusyMessage(from_id, RlvStrings::getVersion(), session_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)
|
// 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(from_id, dialog);
|
||||||
gIMMgr->processIMTypingStop(im_info);
|
|
||||||
}
|
}
|
||||||
// [/RLVa:KB]
|
// [/RLVa:KB]
|
||||||
else if (offline == IM_ONLINE
|
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);
|
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");
|
script_msg_api(from_id.asString() + ", 4");
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IM_TYPING_STOP:
|
case IM_TYPING_STOP:
|
||||||
{
|
{
|
||||||
LLPointer<LLIMInfo> im_info = new LLIMInfo(gMessageSystem);
|
gIMMgr->processIMTypingStop(from_id, dialog);
|
||||||
gIMMgr->processIMTypingStop(im_info);
|
|
||||||
script_msg_api(from_id.asString() + ", 5");
|
script_msg_api(from_id.asString() + ", 5");
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -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);
|
LLUUID session_id = computeSessionID(im_type, from_id);
|
||||||
LLFloaterIMPanel* floater = findFloaterBySession(session_id);
|
LLFloaterIMPanel* im_floater = findFloaterBySession(session_id);
|
||||||
if (floater)
|
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());
|
return LLFloaterChatterBox::getInstance(LLSD());
|
||||||
}
|
}
|
||||||
|
|
||||||
class LLViewerChatterBoxSessionStartReply : public LLHTTPNode
|
class LLViewerChatterBoxSessionStartReply final : public LLHTTPNode
|
||||||
{
|
{
|
||||||
public:
|
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.shortInfo("Used for receiving a reply to a request to initialize an ChatterBox session");
|
||||||
desc.postAPI();
|
desc.postAPI();
|
||||||
@@ -1287,18 +1287,15 @@ public:
|
|||||||
desc.source(__FILE__, __LINE__);
|
desc.source(__FILE__, __LINE__);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void post(ResponsePtr response,
|
void post(ResponsePtr response,
|
||||||
const LLSD& context,
|
const LLSD& context,
|
||||||
const LLSD& input) const
|
const LLSD& input) const override
|
||||||
{
|
{
|
||||||
LLSD body;
|
|
||||||
LLUUID temp_session_id;
|
|
||||||
LLUUID session_id;
|
LLUUID session_id;
|
||||||
bool success;
|
|
||||||
|
|
||||||
body = input["body"];
|
LLSD body = input["body"];
|
||||||
success = body["success"].asBoolean();
|
bool success = body["success"].asBoolean();
|
||||||
temp_session_id = body["temp_session_id"].asUUID();
|
LLUUID temp_session_id = body["temp_session_id"].asUUID();
|
||||||
|
|
||||||
if ( success )
|
if ( success )
|
||||||
{
|
{
|
||||||
@@ -1336,10 +1333,10 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class LLViewerChatterBoxSessionEventReply : public LLHTTPNode
|
class LLViewerChatterBoxSessionEventReply final : public LLHTTPNode
|
||||||
{
|
{
|
||||||
public:
|
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.shortInfo("Used for receiving a reply to a ChatterBox session event");
|
||||||
desc.postAPI();
|
desc.postAPI();
|
||||||
@@ -1348,24 +1345,18 @@ public:
|
|||||||
desc.source(__FILE__, __LINE__);
|
desc.source(__FILE__, __LINE__);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void post(ResponsePtr response,
|
void post(ResponsePtr response,
|
||||||
const LLSD& context,
|
const LLSD& context,
|
||||||
const LLSD& input) const
|
const LLSD& input) const override
|
||||||
{
|
{
|
||||||
LLUUID session_id;
|
|
||||||
bool success;
|
|
||||||
|
|
||||||
LLSD body = input["body"];
|
LLSD body = input["body"];
|
||||||
success = body["success"].asBoolean();
|
bool success = body["success"].asBoolean();
|
||||||
session_id = body["session_id"].asUUID();
|
LLUUID session_id = body["session_id"].asUUID();
|
||||||
|
|
||||||
if ( !success )
|
if ( !success )
|
||||||
{
|
{
|
||||||
//throw an error dialog
|
//throw an error dialog
|
||||||
LLFloaterIMPanel* floater =
|
if (auto* floater = gIMMgr->findFloaterBySession(session_id))
|
||||||
gIMMgr->findFloaterBySession(session_id);
|
|
||||||
|
|
||||||
if (floater)
|
|
||||||
{
|
{
|
||||||
floater->showSessionEventError(
|
floater->showSessionEventError(
|
||||||
body["event"].asString(),
|
body["event"].asString(),
|
||||||
@@ -1378,46 +1369,40 @@ public:
|
|||||||
class LLViewerForceCloseChatterBoxSession: public LLHTTPNode
|
class LLViewerForceCloseChatterBoxSession: public LLHTTPNode
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual void post(ResponsePtr response,
|
void post(ResponsePtr response,
|
||||||
const LLSD& context,
|
const LLSD& context,
|
||||||
const LLSD& input) const
|
const LLSD& input) const override
|
||||||
{
|
{
|
||||||
LLUUID session_id;
|
LLUUID session_id = input["body"]["session_id"].asUUID();
|
||||||
std::string reason;
|
std::string reason = input["body"]["reason"].asString();
|
||||||
|
|
||||||
session_id = input["body"]["session_id"].asUUID();
|
if (auto* floater = gIMMgr ->findFloaterBySession(session_id))
|
||||||
reason = input["body"]["reason"].asString();
|
|
||||||
|
|
||||||
LLFloaterIMPanel* floater =
|
|
||||||
gIMMgr ->findFloaterBySession(session_id);
|
|
||||||
|
|
||||||
if ( floater )
|
|
||||||
{
|
{
|
||||||
floater->showSessionForceClose(reason);
|
floater->showSessionForceClose(reason);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class LLViewerChatterBoxSessionAgentListUpdates : public LLHTTPNode
|
class LLViewerChatterBoxSessionAgentListUpdates final : public LLHTTPNode
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual void post(
|
void post(
|
||||||
ResponsePtr responder,
|
ResponsePtr responder,
|
||||||
const LLSD& context,
|
const LLSD& context,
|
||||||
const LLSD& input) const
|
const LLSD& input) const override
|
||||||
{
|
{
|
||||||
const LLUUID& session_id = input["body"]["session_id"].asUUID();
|
const LLUUID& session_id = input["body"]["session_id"].asUUID();
|
||||||
gIMMgr->processAgentListUpdates(session_id, input["body"]);
|
gIMMgr->processAgentListUpdates(session_id, input["body"]);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class LLViewerChatterBoxSessionUpdate : public LLHTTPNode
|
class LLViewerChatterBoxSessionUpdate final : public LLHTTPNode
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual void post(
|
void post(
|
||||||
ResponsePtr responder,
|
ResponsePtr responder,
|
||||||
const LLSD& context,
|
const LLSD& context,
|
||||||
const LLSD& input) const
|
const LLSD& input) const override
|
||||||
{
|
{
|
||||||
LLUUID session_id = input["body"]["session_id"].asUUID();
|
LLUUID session_id = input["body"]["session_id"].asUUID();
|
||||||
LLFloaterIMPanel* im_floater = gIMMgr->findFloaterBySession(session_id);
|
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);
|
gIMMgr->removeSession(session_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
class LLViewerChatterBoxInvitation : public LLHTTPNode
|
class LLViewerChatterBoxInvitation final : public LLHTTPNode
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
virtual void post(
|
void post(
|
||||||
ResponsePtr response,
|
ResponsePtr response,
|
||||||
const LLSD& context,
|
const LLSD& context,
|
||||||
const LLSD& input) const
|
const LLSD& input) const override
|
||||||
{
|
{
|
||||||
//for backwards compatiblity reasons...we need to still
|
//for backwards compatiblity reasons...we need to still
|
||||||
//check for 'text' or 'voice' invitations...bleh
|
//check for 'text' or 'voice' invitations...bleh
|
||||||
@@ -1582,10 +1567,9 @@ public:
|
|||||||
LLFloaterChat::addChat(chat, TRUE, is_this_agent);
|
LLFloaterChat::addChat(chat, TRUE, is_this_agent);
|
||||||
|
|
||||||
//K now we want to accept the invitation
|
//K now we want to accept the invitation
|
||||||
std::string url = gAgent.getRegion()->getCapability(
|
std::string url = gAgent.getRegionCapability("ChatSessionRequest");
|
||||||
"ChatSessionRequest");
|
|
||||||
|
|
||||||
if ( url != "" )
|
if (!url.empty())
|
||||||
{
|
{
|
||||||
LLSD data;
|
LLSD data;
|
||||||
data["method"] = "accept invitation";
|
data["method"] = "accept invitation";
|
||||||
|
|||||||
@@ -42,7 +42,7 @@
|
|||||||
class LLFloaterChatterBox;
|
class LLFloaterChatterBox;
|
||||||
class LLFloaterIMPanel;
|
class LLFloaterIMPanel;
|
||||||
|
|
||||||
class LLIMMgr : public LLSingleton<LLIMMgr>
|
class LLIMMgr final : public LLSingleton<LLIMMgr>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
enum EInvitationType
|
enum EInvitationType
|
||||||
@@ -121,8 +121,8 @@ public:
|
|||||||
void updateFloaterSessionID(const LLUUID& old_session_id,
|
void updateFloaterSessionID(const LLUUID& old_session_id,
|
||||||
const LLUUID& new_session_id);
|
const LLUUID& new_session_id);
|
||||||
|
|
||||||
void processIMTypingStart(const LLIMInfo* im_info);
|
void processIMTypingStart(const LLUUID& from_id, const EInstantMessage im_type);
|
||||||
void processIMTypingStop(const LLIMInfo* im_info);
|
void processIMTypingStop(const LLUUID& from_id, const EInstantMessage im_type);
|
||||||
|
|
||||||
void clearNewIMNotification();
|
void clearNewIMNotification();
|
||||||
|
|
||||||
@@ -209,7 +209,7 @@ private:
|
|||||||
void noteOfflineUsers(LLFloaterIMPanel* panel, const uuid_vec_t& ids);
|
void noteOfflineUsers(LLFloaterIMPanel* panel, const uuid_vec_t& ids);
|
||||||
void noteMutedUsers(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:
|
private:
|
||||||
std::set<LLHandle<LLFloater> > mFloaters;
|
std::set<LLHandle<LLFloater> > mFloaters;
|
||||||
|
|||||||
Reference in New Issue
Block a user