aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/linden/indra/newview/llimview.cpp
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--linden/indra/newview/llimview.cpp503
1 files changed, 344 insertions, 159 deletions
diff --git a/linden/indra/newview/llimview.cpp b/linden/indra/newview/llimview.cpp
index 468c75e..2f9c1eb 100644
--- a/linden/indra/newview/llimview.cpp
+++ b/linden/indra/newview/llimview.cpp
@@ -12,12 +12,12 @@
12 * ("GPL"), unless you have obtained a separate licensing agreement 12 * ("GPL"), unless you have obtained a separate licensing agreement
13 * ("Other License"), formally executed by you and Linden Lab. Terms of 13 * ("Other License"), formally executed by you and Linden Lab. Terms of
14 * the GPL can be found in doc/GPL-license.txt in this distribution, or 14 * the GPL can be found in doc/GPL-license.txt in this distribution, or
15 * online at http://secondlife.com/developers/opensource/gplv2 15 * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
16 * 16 *
17 * There are special exceptions to the terms and conditions of the GPL as 17 * There are special exceptions to the terms and conditions of the GPL as
18 * it is applied to this Source Code. View the full text of the exception 18 * it is applied to this Source Code. View the full text of the exception
19 * in the file doc/FLOSS-exception.txt in this software distribution, or 19 * in the file doc/FLOSS-exception.txt in this software distribution, or
20 * online at http://secondlife.com/developers/opensource/flossexception 20 * online at http://secondlifegrid.net/programs/open_source/licensing/flossexception
21 * 21 *
22 * By copying, modifying or distributing this software, you acknowledge 22 * By copying, modifying or distributing this software, you acknowledge
23 * that you have read and understood your obligations described above, 23 * that you have read and understood your obligations described above,
@@ -46,7 +46,6 @@
46#include "llagent.h" 46#include "llagent.h"
47#include "llcallingcard.h" 47#include "llcallingcard.h"
48#include "llchat.h" 48#include "llchat.h"
49#include "llviewerwindow.h"
50#include "llresmgr.h" 49#include "llresmgr.h"
51#include "llfloaterchat.h" 50#include "llfloaterchat.h"
52#include "llfloaterchatterbox.h" 51#include "llfloaterchatterbox.h"
@@ -65,6 +64,7 @@
65#include "llcallingcard.h" 64#include "llcallingcard.h"
66#include "lltoolbar.h" 65#include "lltoolbar.h"
67#include "llviewermessage.h" 66#include "llviewermessage.h"
67#include "llviewerwindow.h"
68#include "llnotify.h" 68#include "llnotify.h"
69#include "llviewerregion.h" 69#include "llviewerregion.h"
70 70
@@ -84,11 +84,12 @@ LLIMMgr* gIMMgr = NULL;
84//*FIXME: make these all either UIStrings or Strings 84//*FIXME: make these all either UIStrings or Strings
85static LLString sOnlyUserMessage; 85static LLString sOnlyUserMessage;
86static LLUIString sOfflineMessage; 86static LLUIString sOfflineMessage;
87
88static std::map<std::string,LLString> sEventStringsMap;
89static std::map<std::string,LLString> sErrorStringsMap;
90static std::map<std::string,LLString> sForceCloseSessionMap;
91static LLUIString sInviteMessage; 87static LLUIString sInviteMessage;
88
89std::map<std::string,LLString> LLFloaterIM::sEventStringsMap;
90std::map<std::string,LLString> LLFloaterIM::sErrorStringsMap;
91std::map<std::string,LLString> LLFloaterIM::sForceCloseSessionMap;
92
92// 93//
93// Helper Functions 94// Helper Functions
94// 95//
@@ -160,22 +161,82 @@ BOOL LLFloaterIM::postBuild()
160 sOnlyUserMessage = getFormattedUIString("only_user_message"); 161 sOnlyUserMessage = getFormattedUIString("only_user_message");
161 sOfflineMessage = getUIString("offline_message"); 162 sOfflineMessage = getUIString("offline_message");
162 163
163 sErrorStringsMap["generic"] = 164 sInviteMessage = getUIString("invite_message");
164 getFormattedUIString("generic_request_error"); 165
165 sErrorStringsMap["unverified"] = 166 if ( sErrorStringsMap.find("generic") == sErrorStringsMap.end() )
166 getFormattedUIString("insufficient_perms_error"); 167 {
167 sErrorStringsMap["no_user_911"] = 168 sErrorStringsMap["generic"] =
168 getFormattedUIString("user_no_help"); 169 getFormattedUIString("generic_request_error");
170 }
171
172 if ( sErrorStringsMap.find("unverified") ==
173 sErrorStringsMap.end() )
174 {
175 sErrorStringsMap["unverified"] =
176 getFormattedUIString("insufficient_perms_error");
177 }
178
179 if ( sErrorStringsMap.end() ==
180 sErrorStringsMap.find("no_ability") )
181 {
182 sErrorStringsMap["no_ability"] =
183 getFormattedUIString("no_ability_error");
184 }
169 185
170 sEventStringsMap["add"] = 186 if ( sErrorStringsMap.end() ==
171 getFormattedUIString("add_session_event"); 187 sErrorStringsMap.find("muted") )
172 sEventStringsMap["message"] = 188 {
173 getFormattedUIString("message_session_event"); 189 sErrorStringsMap["muted"] =
190 getFormattedUIString("muted_error");
191 }
174 192
175 sForceCloseSessionMap["removed"] = 193 if ( sErrorStringsMap.end() ==
176 getFormattedUIString("removed_from_group"); 194 sErrorStringsMap.find("not_a_moderator") )
195 {
196 sErrorStringsMap["not_a_moderator"] =
197 getFormattedUIString("not_a_mod_error");
198 }
199
200 if ( sErrorStringsMap.end() ==
201 sErrorStringsMap.find("does not exist") )
202 {
203 sErrorStringsMap["does not exist"] =
204 getFormattedUIString("session_does_not_exist_error");
205 }
206
207 if ( sEventStringsMap.end() == sEventStringsMap.find("add") )
208 {
209 sEventStringsMap["add"] =
210 getFormattedUIString("add_session_event");
211 }
212
213 if ( sEventStringsMap.end() == sEventStringsMap.find("message") )
214 {
215 sEventStringsMap["message"] =
216 getFormattedUIString("message_session_event");
217 }
218
219
220 if ( sEventStringsMap.end() == sEventStringsMap.find("mute") )
221 {
222 sEventStringsMap["mute"] = getFormattedUIString(
223 "mute_agent_event");
224 }
225
226 if ( sForceCloseSessionMap.end() ==
227 sForceCloseSessionMap.find("removed") )
228 {
229 sForceCloseSessionMap["removed"] =
230 getFormattedUIString("removed_from_group");
231 }
232
233 if ( sForceCloseSessionMap.end() ==
234 sForceCloseSessionMap.find("no ability") )
235 {
236 sForceCloseSessionMap["no ability"] =
237 getFormattedUIString("close_on_no_ability");
238 }
177 239
178 sInviteMessage = getUIString("invite_message");
179 return TRUE; 240 return TRUE;
180} 241}
181 242
@@ -205,21 +266,31 @@ protected:
205class LLIMMgr::LLIMSessionInvite 266class LLIMMgr::LLIMSessionInvite
206{ 267{
207public: 268public:
208 LLIMSessionInvite(const LLUUID& session_id, const LLString& session_name, const LLUUID& caller_id,const LLString& caller_name, EInstantMessage type, const LLString& session_handle, const LLString& notify_box) : 269 LLIMSessionInvite(
209 mSessionID(session_id), 270 const LLUUID& session_id,
210 mSessionName(session_name), 271 const LLString& session_name,
211 mCallerID(caller_id), 272 const LLUUID& caller_id,
212 mCallerName(caller_name), 273 const LLString& caller_name,
213 mType(type), 274 EInstantMessage type,
214 mSessionHandle(session_handle), 275 EInvitationType inv_type,
215 mNotifyBox(notify_box) 276 const LLString& session_handle,
216 {}; 277 const LLString& notify_box) :
278 mSessionID(session_id),
279 mSessionName(session_name),
280 mCallerID(caller_id),
281 mCallerName(caller_name),
282 mType(type),
283 mInvType(inv_type),
284 mSessionHandle(session_handle),
285 mNotifyBox(notify_box)
286 {};
217 287
218 LLUUID mSessionID; 288 LLUUID mSessionID;
219 LLString mSessionName; 289 LLString mSessionName;
220 LLUUID mCallerID; 290 LLUUID mCallerID;
221 LLString mCallerName; 291 LLString mCallerName;
222 EInstantMessage mType; 292 EInstantMessage mType;
293 EInvitationType mInvType;
223 LLString mSessionHandle; 294 LLString mSessionHandle;
224 LLString mNotifyBox; 295 LLString mNotifyBox;
225}; 296};
@@ -309,7 +380,7 @@ LLIMMgr::LLIMMgr() :
309 LLFloaterIM* dummy_floater = new LLFloaterIM(); 380 LLFloaterIM* dummy_floater = new LLFloaterIM();
310 delete dummy_floater; 381 delete dummy_floater;
311 382
312 mPendingVoiceInvitations = LLSD::emptyMap(); 383 mPendingInvitations = LLSD::emptyMap();
313 mPendingAgentListUpdates = LLSD::emptyMap(); 384 mPendingAgentListUpdates = LLSD::emptyMap();
314} 385}
315 386
@@ -413,7 +484,6 @@ void LLIMMgr::addMessage(
413 if ( is_from_system ) // chat came from system 484 if ( is_from_system ) // chat came from system
414 { 485 {
415 floater->addHistoryLine( 486 floater->addHistoryLine(
416 other_participant_id,
417 msg, 487 msg,
418 gSavedSettings.getColor4("SystemChatColor")); 488 gSavedSettings.getColor4("SystemChatColor"));
419 } 489 }
@@ -521,9 +591,10 @@ LLUUID LLIMMgr::addP2PSession(const std::string& name,
521// the session, dialog specifies the type of session. If the session 591// the session, dialog specifies the type of session. If the session
522// exists, it is brought forward. Specifying id = NULL results in an 592// exists, it is brought forward. Specifying id = NULL results in an
523// im session to everyone. Returns the uuid of the session. 593// im session to everyone. Returns the uuid of the session.
524LLUUID LLIMMgr::addSession(const std::string& name, 594LLUUID LLIMMgr::addSession(
525 EInstantMessage dialog, 595 const std::string& name,
526 const LLUUID& other_participant_id) 596 EInstantMessage dialog,
597 const LLUUID& other_participant_id)
527{ 598{
528 LLUUID session_id = computeSessionID(dialog, other_participant_id); 599 LLUUID session_id = computeSessionID(dialog, other_participant_id);
529 600
@@ -533,15 +604,16 @@ LLUUID LLIMMgr::addSession(const std::string& name,
533 LLDynamicArray<LLUUID> ids; 604 LLDynamicArray<LLUUID> ids;
534 ids.put(other_participant_id); 605 ids.put(other_participant_id);
535 606
536 floater = createFloater(session_id, 607 floater = createFloater(
537 other_participant_id, 608 session_id,
538 name, 609 other_participant_id,
539 ids, 610 name,
540 dialog, 611 ids,
541 TRUE); 612 dialog,
613 TRUE);
542 614
543 noteOfflineUsers(floater, ids); 615 noteOfflineUsers(floater, ids);
544 LLFloaterChatterBox::getInstance(LLSD())->showFloater(floater); 616 LLFloaterChatterBox::showInstance(session_id);
545 } 617 }
546 else 618 else
547 { 619 {
@@ -554,36 +626,43 @@ LLUUID LLIMMgr::addSession(const std::string& name,
554 626
555// Adds a session using the given session_id. If the session already exists 627// Adds a session using the given session_id. If the session already exists
556// the dialog type is assumed correct. Returns the uuid of the session. 628// the dialog type is assumed correct. Returns the uuid of the session.
557LLUUID LLIMMgr::addSession(const std::string& name, 629LLUUID LLIMMgr::addSession(
558 EInstantMessage dialog, 630 const std::string& name,
559 const LLUUID& other_participant_id, 631 EInstantMessage dialog,
560 const LLDynamicArray<LLUUID>& ids) 632 const LLUUID& other_participant_id,
633 const LLDynamicArray<LLUUID>& ids)
561{ 634{
562 if (0 == ids.getLength()) 635 if (0 == ids.getLength())
563 { 636 {
564 return LLUUID::null; 637 return LLUUID::null;
565 } 638 }
566 639
567 LLUUID session_id = computeSessionID(dialog, 640 LLUUID session_id = computeSessionID(
568 other_participant_id); 641 dialog,
642 other_participant_id);
569 643
570 LLFloaterIMPanel* floater = findFloaterBySession(session_id); 644 LLFloaterIMPanel* floater = findFloaterBySession(session_id);
571 if(!floater) 645 if(!floater)
572 { 646 {
573 // On creation, use the first element of ids as the 647 // On creation, use the first element of ids as the
574 // "other_participant_id" 648 // "other_participant_id"
575 floater = createFloater(session_id, 649 floater = createFloater(
576 other_participant_id, 650 session_id,
577 name, 651 other_participant_id,
578 ids, 652 name,
579 dialog, 653 ids,
580 TRUE); 654 dialog,
655 TRUE);
581 656
582 if ( !floater ) return LLUUID::null; 657 if ( !floater ) return LLUUID::null;
583 658
584 noteOfflineUsers(floater, ids); 659 noteOfflineUsers(floater, ids);
660 LLFloaterChatterBox::showInstance(session_id);
661 }
662 else
663 {
664 floater->open();
585 } 665 }
586 LLFloaterChatterBox::getInstance(LLSD())->showFloater(floater);
587 //mTabContainer->selectTabPanel(panel); 666 //mTabContainer->selectTabPanel(panel);
588 floater->setInputFocus(TRUE); 667 floater->setInputFocus(TRUE);
589 return floater->getSessionID(); 668 return floater->getSessionID();
@@ -599,6 +678,9 @@ void LLIMMgr::removeSession(const LLUUID& session_id)
599 mFloaters.erase(floater->getHandle()); 678 mFloaters.erase(floater->getHandle());
600 LLFloaterChatterBox::getInstance(LLSD())->removeFloater(floater); 679 LLFloaterChatterBox::getInstance(LLSD())->removeFloater(floater);
601 //mTabContainer->removeTabPanel(floater); 680 //mTabContainer->removeTabPanel(floater);
681
682 clearPendingInviation(session_id);
683 clearPendingAgentListUpdates(session_id);
602 } 684 }
603} 685}
604 686
@@ -608,9 +690,10 @@ void LLIMMgr::inviteToSession(
608 const LLUUID& caller_id, 690 const LLUUID& caller_id,
609 const LLString& caller_name, 691 const LLString& caller_name,
610 EInstantMessage type, 692 EInstantMessage type,
693 EInvitationType inv_type,
611 const LLString& session_handle) 694 const LLString& session_handle)
612{ 695{
613 //ignore voice invites from voice-muted residents 696 //ignore invites from muted residents
614 if (gMuteListp->isMuted(caller_id)) 697 if (gMuteListp->isMuted(caller_id))
615 { 698 {
616 return; 699 return;
@@ -621,17 +704,26 @@ void LLIMMgr::inviteToSession(
621 BOOL ad_hoc_invite = FALSE; 704 BOOL ad_hoc_invite = FALSE;
622 if(type == IM_SESSION_P2P_INVITE) 705 if(type == IM_SESSION_P2P_INVITE)
623 { 706 {
707 //P2P is different...they only have voice invitations
624 notify_box_type = "VoiceInviteP2P"; 708 notify_box_type = "VoiceInviteP2P";
625 } 709 }
626 else if (gAgent.isInGroup(session_id)) 710 else if ( gAgent.isInGroup(session_id) )
627 { 711 {
712 //only really old school groups have voice invitations
628 notify_box_type = "VoiceInviteGroup"; 713 notify_box_type = "VoiceInviteGroup";
629 } 714 }
630 else 715 else if ( inv_type == INVITATION_TYPE_VOICE )
631 { 716 {
717 //else it's an ad-hoc
718 //and a voice ad-hoc
632 notify_box_type = "VoiceInviteAdHoc"; 719 notify_box_type = "VoiceInviteAdHoc";
633 ad_hoc_invite = TRUE; 720 ad_hoc_invite = TRUE;
634 } 721 }
722 else if ( inv_type == INVITATION_TYPE_IMMEDIATE )
723 {
724 notify_box_type = "InviteAdHoc";
725 ad_hoc_invite = TRUE;
726 }
635 727
636 LLIMSessionInvite* invite = new LLIMSessionInvite( 728 LLIMSessionInvite* invite = new LLIMSessionInvite(
637 session_id, 729 session_id,
@@ -639,6 +731,7 @@ void LLIMMgr::inviteToSession(
639 caller_id, 731 caller_id,
640 caller_name, 732 caller_name,
641 type, 733 type,
734 inv_type,
642 session_handle, 735 session_handle,
643 notify_box_type); 736 notify_box_type);
644 737
@@ -666,7 +759,7 @@ void LLIMMgr::inviteToSession(
666 } 759 }
667 } 760 }
668 761
669 if ( !mPendingVoiceInvitations.has(session_id.asString()) ) 762 if ( !mPendingInvitations.has(session_id.asString()) )
670 { 763 {
671 if (caller_name.empty()) 764 if (caller_name.empty())
672 { 765 {
@@ -684,7 +777,7 @@ void LLIMMgr::inviteToSession(
684 (void*)invite); 777 (void*)invite);
685 778
686 } 779 }
687 mPendingVoiceInvitations[session_id.asString()] = LLSD(); 780 mPendingInvitations[session_id.asString()] = LLSD();
688 } 781 }
689} 782}
690 783
@@ -699,10 +792,11 @@ void LLIMMgr::onInviteNameLookup(const LLUUID& id, const char* first, const char
699 LLString::format_map_t args; 792 LLString::format_map_t args;
700 args["[NAME]"] = invite->mCallerName; 793 args["[NAME]"] = invite->mCallerName;
701 794
702 LLNotifyBox::showXml(invite->mNotifyBox, 795 LLNotifyBox::showXml(
703 args, 796 invite->mNotifyBox,
704 inviteUserResponse, 797 args,
705 (void*)invite); 798 inviteUserResponse,
799 (void*)invite);
706} 800}
707 801
708class LLViewerChatterBoxInvitationAcceptResponder : 802class LLViewerChatterBoxInvitationAcceptResponder :
@@ -711,10 +805,10 @@ class LLViewerChatterBoxInvitationAcceptResponder :
711public: 805public:
712 LLViewerChatterBoxInvitationAcceptResponder( 806 LLViewerChatterBoxInvitationAcceptResponder(
713 const LLUUID& session_id, 807 const LLUUID& session_id,
714 bool is_voice_invitation) 808 LLIMMgr::EInvitationType invitation_type)
715 { 809 {
716 mSessionID = session_id; 810 mSessionID = session_id;
717 mIsVoiceInvitiation = is_voice_invitation; 811 mInvitiationType = invitation_type;
718 } 812 }
719 813
720 void result(const LLSD& content) 814 void result(const LLSD& content)
@@ -738,48 +832,66 @@ public:
738 //but unfortunately, our base that we are receiving here 832 //but unfortunately, our base that we are receiving here
739 //may not be the most up to date. It was accurate at 833 //may not be the most up to date. It was accurate at
740 //some point in time though. 834 //some point in time though.
741 floaterp->setSpeakersList(content["agents"]); 835 floaterp->setSpeakers(content);
742 836
743 //we now have our base of users in the session 837 //we now have our base of users in the session
744 //that was accurate at some point, but maybe not now 838 //that was accurate at some point, but maybe not now
745 //so now we apply all of the udpates we've received 839 //so now we apply all of the udpates we've received
746 //in case of race conditions 840 //in case of race conditions
747
748 //reapplying a user entrance will do nothing
749 //reapplying a user leaving will not have the user
750 //in our base. So it's all good
751 floaterp->updateSpeakersList( 841 floaterp->updateSpeakersList(
752 gIMMgr->getPendingAgentListUpdates(mSessionID)); 842 gIMMgr->getPendingAgentListUpdates(mSessionID));
753 843
754 if ( mIsVoiceInvitiation ) 844 if ( mInvitiationType == LLIMMgr::INVITATION_TYPE_VOICE )
755 { 845 {
756 floaterp->requestAutoConnect(); 846 floaterp->requestAutoConnect();
757 LLFloaterIMPanel::onClickStartCall(floaterp); 847 LLFloaterIMPanel::onClickStartCall(floaterp);
758 // always open IM window when connecting to voice 848 // always open IM window when connecting to voice
759 LLFloaterChatterBox::showInstance(TRUE); 849 LLFloaterChatterBox::showInstance(TRUE);
760 } 850 }
851 else if ( mInvitiationType == LLIMMgr::INVITATION_TYPE_IMMEDIATE )
852 {
853 LLFloaterChatterBox::showInstance(TRUE);
854 }
761 } 855 }
762 856
763 gIMMgr->clearPendingAgentListUpdates(mSessionID); 857 gIMMgr->clearPendingAgentListUpdates(mSessionID);
764 if ( mIsVoiceInvitiation ) 858 gIMMgr->clearPendingInviation(mSessionID);
765 {
766 gIMMgr->clearPendingVoiceInviation(mSessionID);
767 }
768 } 859 }
769 } 860 }
770 861
771 void error(U32 statusNum, const std::string& reason) 862 void error(U32 statusNum, const std::string& reason)
772 { 863 {
773 //throw something back to the viewer here? 864 //throw something back to the viewer here?
774 if ( gIMMgr && mIsVoiceInvitiation ) 865 if ( gIMMgr )
775 { 866 {
776 gIMMgr->clearPendingVoiceInviation(mSessionID); 867 gIMMgr->clearPendingAgentListUpdates(mSessionID);
868 gIMMgr->clearPendingInviation(mSessionID);
869
870 LLFloaterIMPanel* floaterp =
871 gIMMgr->findFloaterBySession(mSessionID);
872
873 if ( floaterp )
874 {
875 std::string error_string;
876
877 if ( 404 == statusNum )
878 {
879 error_string = "does not exist";
880 }
881 else
882 {
883 error_string = "generic";
884 }
885
886 floaterp->showSessionStartError(
887 error_string);
888 }
777 } 889 }
778 } 890 }
779 891
780private: 892private:
781 LLUUID mSessionID; 893 LLUUID mSessionID;
782 bool mIsVoiceInvitiation; 894 LLIMMgr::EInvitationType mInvitiationType;
783}; 895};
784 896
785//static 897//static
@@ -807,10 +919,11 @@ void LLIMMgr::inviteUserResponse(S32 option, void* user_data)
807 im_floater->requestAutoConnect(); 919 im_floater->requestAutoConnect();
808 LLFloaterIMPanel::onClickStartCall(im_floater); 920 LLFloaterIMPanel::onClickStartCall(im_floater);
809 // always open IM window when connecting to voice 921 // always open IM window when connecting to voice
810 LLFloaterChatterBox::showInstance(TRUE); 922 LLFloaterChatterBox::showInstance(invitep->mSessionID);
811 } 923 }
812 924
813 gIMMgr->clearPendingVoiceInviation(invitep->mSessionID); 925 gIMMgr->clearPendingAgentListUpdates(invitep->mSessionID);
926 gIMMgr->clearPendingInviation(invitep->mSessionID);
814 } 927 }
815 else 928 else
816 { 929 {
@@ -830,34 +943,50 @@ void LLIMMgr::inviteUserResponse(S32 option, void* user_data)
830 data, 943 data,
831 new LLViewerChatterBoxInvitationAcceptResponder( 944 new LLViewerChatterBoxInvitationAcceptResponder(
832 invitep->mSessionID, 945 invitep->mSessionID,
833 true)); 946 invitep->mInvType));
834 } 947 }
835 } 948 }
836 break; 949 break;
837 case 2: // mute (also implies ignore, so this falls through to the "ignore" case below) 950 case 2: // mute (also implies ignore, so this falls through to the "ignore" case below)
951 {
952 // mute the sender of this invite
953 if (!gMuteListp->isMuted(invitep->mCallerID))
838 { 954 {
839 // mute the sender of this invite 955 LLMute mute(invitep->mCallerID, invitep->mCallerName, LLMute::AGENT);
840 if (!gMuteListp->isMuted(invitep->mCallerID)) 956 gMuteListp->add(mute);
841 {
842 LLMute mute(invitep->mCallerID, invitep->mCallerName, LLMute::AGENT);
843 gMuteListp->add(mute);
844 }
845 } 957 }
958 }
846 /* FALLTHROUGH */ 959 /* FALLTHROUGH */
847 960
848 case 1: // ignore 961 case 1: // decline
962 {
963 if (invitep->mType == IM_SESSION_P2P_INVITE)
849 { 964 {
850 if (invitep->mType == IM_SESSION_P2P_INVITE) 965 if(gVoiceClient)
851 { 966 {
852 if(gVoiceClient) 967 gVoiceClient->declineInvite(invitep->mSessionHandle);
853 {
854 gVoiceClient->declineInvite(invitep->mSessionHandle);
855 }
856 } 968 }
857 } 969 }
858 break; 970 else
971 {
972 std::string url = gAgent.getRegion()->getCapability(
973 "ChatSessionRequest");
974
975 LLSD data;
976 data["method"] = "decline invitation";
977 data["session-id"] = invitep->mSessionID;
978 LLHTTPClient::post(
979 url,
980 data,
981 NULL);
982 }
859 } 983 }
860 984
985 gIMMgr->clearPendingAgentListUpdates(invitep->mSessionID);
986 gIMMgr->clearPendingInviation(invitep->mSessionID);
987 break;
988 }
989
861 delete invitep; 990 delete invitep;
862} 991}
863 992
@@ -869,11 +998,11 @@ void LLIMMgr::setFloaterOpen(BOOL set_open)
869{ 998{
870 if (set_open) 999 if (set_open)
871 { 1000 {
872 LLFloaterChatterBox::showInstance(LLSD()); 1001 LLFloaterChatterBox::showInstance();
873 } 1002 }
874 else 1003 else
875 { 1004 {
876 LLFloaterChatterBox::hideInstance(LLSD()); 1005 LLFloaterChatterBox::hideInstance();
877 } 1006 }
878} 1007}
879 1008
@@ -932,11 +1061,11 @@ BOOL LLIMMgr::hasSession(const LLUUID& session_id)
932 return (findFloaterBySession(session_id) != NULL); 1061 return (findFloaterBySession(session_id) != NULL);
933} 1062}
934 1063
935void LLIMMgr::clearPendingVoiceInviation(const LLUUID& session_id) 1064void LLIMMgr::clearPendingInviation(const LLUUID& session_id)
936{ 1065{
937 if ( mPendingVoiceInvitations.has(session_id.asString()) ) 1066 if ( mPendingInvitations.has(session_id.asString()) )
938 { 1067 {
939 mPendingVoiceInvitations.erase(session_id.asString()); 1068 mPendingInvitations.erase(session_id.asString());
940 } 1069 }
941} 1070}
942 1071
@@ -958,13 +1087,57 @@ void LLIMMgr::addPendingAgentListUpdates(
958{ 1087{
959 LLSD::map_const_iterator iter; 1088 LLSD::map_const_iterator iter;
960 1089
961 for ( iter = updates.beginMap(); 1090 if ( !mPendingAgentListUpdates.has(session_id.asString()) )
962 iter != updates.endMap(); 1091 {
963 iter++) 1092 //this is a new agent list update for this session
1093 mPendingAgentListUpdates[session_id.asString()] = LLSD::emptyMap();
1094 }
1095
1096 if (
1097 updates.has("agent_updates") &&
1098 updates["agent_updates"].isMap() &&
1099 updates.has("updates") &&
1100 updates["updates"].isMap() )
1101 {
1102 //new school update
1103 LLSD update_types = LLSD::emptyArray();
1104 LLSD::array_iterator array_iter;
1105
1106 update_types.append("agent_updates");
1107 update_types.append("updates");
1108
1109 for (
1110 array_iter = update_types.beginArray();
1111 array_iter != update_types.endArray();
1112 ++array_iter)
1113 {
1114 //we only want to include the last update for a given agent
1115 for (
1116 iter = updates[array_iter->asString()].beginMap();
1117 iter != updates[array_iter->asString()].endMap();
1118 ++iter)
1119 {
1120 mPendingAgentListUpdates[session_id.asString()][array_iter->asString()][iter->first] =
1121 iter->second;
1122 }
1123 }
1124 }
1125 else if (
1126 updates.has("updates") &&
1127 updates["updates"].isMap() )
964 { 1128 {
965 //we only want to include the last update for a given agent 1129 //old school update where the SD contained just mappings
966 mPendingAgentListUpdates[session_id.asString()][iter->first] = 1130 //of agent_id -> "LEAVE"/"ENTER"
967 iter->second; 1131
1132 //only want to keep last update for each agent
1133 for (
1134 iter = updates["updates"].beginMap();
1135 iter != updates["updates"].endMap();
1136 ++iter)
1137 {
1138 mPendingAgentListUpdates[session_id.asString()]["updates"][iter->first] =
1139 iter->second;
1140 }
968 } 1141 }
969} 1142}
970 1143
@@ -995,8 +1168,6 @@ LLFloaterIMPanel* LLIMMgr::createFloater(
995 llinfos << "LLIMMgr::createFloater: from " << other_participant_id 1168 llinfos << "LLIMMgr::createFloater: from " << other_participant_id
996 << " in session " << session_id << llendl; 1169 << " in session " << session_id << llendl;
997 LLFloaterIMPanel* floater = new LLFloaterIMPanel(session_label, 1170 LLFloaterIMPanel* floater = new LLFloaterIMPanel(session_label,
998 LLRect(),
999 session_label,
1000 session_id, 1171 session_id,
1001 other_participant_id, 1172 other_participant_id,
1002 dialog); 1173 dialog);
@@ -1022,8 +1193,6 @@ LLFloaterIMPanel* LLIMMgr::createFloater(
1022 llinfos << "LLIMMgr::createFloater: from " << other_participant_id 1193 llinfos << "LLIMMgr::createFloater: from " << other_participant_id
1023 << " in session " << session_id << llendl; 1194 << " in session " << session_id << llendl;
1024 LLFloaterIMPanel* floater = new LLFloaterIMPanel(session_label, 1195 LLFloaterIMPanel* floater = new LLFloaterIMPanel(session_label,
1025 LLRect(),
1026 session_label,
1027 session_id, 1196 session_id,
1028 other_participant_id, 1197 other_participant_id,
1029 ids, 1198 ids,
@@ -1034,8 +1203,9 @@ LLFloaterIMPanel* LLIMMgr::createFloater(
1034 return floater; 1203 return floater;
1035} 1204}
1036 1205
1037void LLIMMgr::noteOfflineUsers(LLFloaterIMPanel* floater, 1206void LLIMMgr::noteOfflineUsers(
1038 const LLDynamicArray<LLUUID>& ids) 1207 LLFloaterIMPanel* floater,
1208 const LLDynamicArray<LLUUID>& ids)
1039{ 1209{
1040 S32 count = ids.count(); 1210 S32 count = ids.count();
1041 if(count == 0) 1211 if(count == 0)
@@ -1099,14 +1269,6 @@ LLFloaterChatterBox* LLIMMgr::getFloater()
1099 return LLFloaterChatterBox::getInstance(LLSD()); 1269 return LLFloaterChatterBox::getInstance(LLSD());
1100} 1270}
1101 1271
1102void onConfirmForceCloseError(S32 option, void* data)
1103{
1104 //only 1 option really
1105 LLFloaterIMPanel* floater = ((LLFloaterIMPanel*) data);
1106
1107 if ( floater ) floater->close(FALSE);
1108}
1109
1110class LLViewerChatterBoxSessionStartReply : public LLHTTPNode 1272class LLViewerChatterBoxSessionStartReply : public LLHTTPNode
1111{ 1273{
1112public: 1274public:
@@ -1141,7 +1303,16 @@ public:
1141 LLFloaterIMPanel* floaterp = gIMMgr->findFloaterBySession(session_id); 1303 LLFloaterIMPanel* floaterp = gIMMgr->findFloaterBySession(session_id);
1142 if (floaterp) 1304 if (floaterp)
1143 { 1305 {
1144 floaterp->setSpeakersList(body["agents"]); 1306 floaterp->setSpeakers(body);
1307
1308 //apply updates we've possibly received previously
1309 floaterp->updateSpeakersList(
1310 gIMMgr->getPendingAgentListUpdates(session_id));
1311
1312 if ( body.has("session_info") )
1313 {
1314 floaterp->processSessionUpdate(body["session_info"]);
1315 }
1145 1316
1146 //aply updates we've possibly received previously 1317 //aply updates we've possibly received previously
1147 floaterp->updateSpeakersList( 1318 floaterp->updateSpeakersList(
@@ -1155,20 +1326,14 @@ public:
1155 //floater 1326 //floater
1156 LLFloaterIMPanel* floater = 1327 LLFloaterIMPanel* floater =
1157 gIMMgr->findFloaterBySession(temp_session_id); 1328 gIMMgr->findFloaterBySession(temp_session_id);
1158 if (floater)
1159 {
1160 LLString::format_map_t args;
1161 args["[REASON]"] =
1162 sErrorStringsMap[body["error"].asString()];
1163 args["[RECIPIENT]"] = floater->getTitle();
1164
1165 gViewerWindow->alertXml("ChatterBoxSessionStartError",
1166 args,
1167 onConfirmForceCloseError,
1168 floater);
1169 1329
1330 if ( floater )
1331 {
1332 floater->showSessionStartError(body["error"].asString());
1170 } 1333 }
1171 } 1334 }
1335
1336 gIMMgr->clearPendingAgentListUpdates(session_id);
1172 } 1337 }
1173}; 1338};
1174 1339
@@ -1200,17 +1365,12 @@ public:
1200 //throw an error dialog 1365 //throw an error dialog
1201 LLFloaterIMPanel* floater = 1366 LLFloaterIMPanel* floater =
1202 gIMMgr->findFloaterBySession(session_id); 1367 gIMMgr->findFloaterBySession(session_id);
1368
1203 if (floater) 1369 if (floater)
1204 { 1370 {
1205 LLString::format_map_t args; 1371 floater->showSessionEventError(
1206 args["[REASON]"] = 1372 body["event"].asString(),
1207 sErrorStringsMap[body["error"].asString()]; 1373 body["error"].asString());
1208 args["[EVENT]"] =
1209 sEventStringsMap[body["event"].asString()];
1210 args["[RECIPIENT]"] = floater->getTitle();
1211
1212 gViewerWindow->alertXml("ChatterBoxSessionEventError",
1213 args);
1214 } 1374 }
1215 } 1375 }
1216 } 1376 }
@@ -1234,15 +1394,7 @@ public:
1234 1394
1235 if ( floater ) 1395 if ( floater )
1236 { 1396 {
1237 LLString::format_map_t args; 1397 floater->showSessionForceClose(reason);
1238
1239 args["[NAME]"] = floater->getTitle();
1240 args["[REASON]"] = sForceCloseSessionMap[reason];
1241
1242 gViewerWindow->alertXml("ForceCloseChatterBoxSession",
1243 args,
1244 onConfirmForceCloseError,
1245 floater);
1246 } 1398 }
1247 } 1399 }
1248}; 1400};
@@ -1258,7 +1410,8 @@ public:
1258 LLFloaterIMPanel* floaterp = gIMMgr->findFloaterBySession(input["body"]["session_id"].asUUID()); 1410 LLFloaterIMPanel* floaterp = gIMMgr->findFloaterBySession(input["body"]["session_id"].asUUID());
1259 if (floaterp) 1411 if (floaterp)
1260 { 1412 {
1261 floaterp->updateSpeakersList(input["body"]["updates"]); 1413 floaterp->updateSpeakersList(
1414 input["body"]);
1262 } 1415 }
1263 else 1416 else
1264 { 1417 {
@@ -1267,11 +1420,28 @@ public:
1267 //a start or an acceptance of an invitation. Race condition. 1420 //a start or an acceptance of an invitation. Race condition.
1268 gIMMgr->addPendingAgentListUpdates( 1421 gIMMgr->addPendingAgentListUpdates(
1269 input["body"]["session_id"].asUUID(), 1422 input["body"]["session_id"].asUUID(),
1270 input["body"]["updates"]); 1423 input["body"]);
1271 } 1424 }
1272 } 1425 }
1273}; 1426};
1274 1427
1428class LLViewerChatterBoxSessionUpdate : public LLHTTPNode
1429{
1430public:
1431 virtual void post(
1432 ResponsePtr responder,
1433 const LLSD& context,
1434 const LLSD& input) const
1435 {
1436 LLFloaterIMPanel* floaterp = gIMMgr->findFloaterBySession(input["body"]["session_id"].asUUID());
1437 if (floaterp)
1438 {
1439 floaterp->processSessionUpdate(input["body"]["info"]);
1440 }
1441 }
1442};
1443
1444
1275class LLViewerChatterBoxInvitation : public LLHTTPNode 1445class LLViewerChatterBoxInvitation : public LLHTTPNode
1276{ 1446{
1277public: 1447public:
@@ -1281,10 +1451,10 @@ public:
1281 const LLSD& context, 1451 const LLSD& context,
1282 const LLSD& input) const 1452 const LLSD& input) const
1283 { 1453 {
1454 //for backwards compatiblity reasons...we need to still
1455 //check for 'text' or 'voice' invitations...bleh
1284 if ( input["body"].has("instantmessage") ) 1456 if ( input["body"].has("instantmessage") )
1285 { 1457 {
1286 LLString capability = input["body"]["capabilities"]["call"].asString();
1287
1288 LLSD message_params = 1458 LLSD message_params =
1289 input["body"]["instantmessage"]["message_params"]; 1459 input["body"]["instantmessage"]["message_params"];
1290 1460
@@ -1392,13 +1562,13 @@ public:
1392 { 1562 {
1393 LLSD data; 1563 LLSD data;
1394 data["method"] = "accept invitation"; 1564 data["method"] = "accept invitation";
1395 data["session-id"] = input["body"]["session_id"]; 1565 data["session-id"] = session_id;
1396 LLHTTPClient::post( 1566 LLHTTPClient::post(
1397 url, 1567 url,
1398 data, 1568 data,
1399 new LLViewerChatterBoxInvitationAcceptResponder( 1569 new LLViewerChatterBoxInvitationAcceptResponder(
1400 input["body"]["session_id"], 1570 session_id,
1401 false)); 1571 LLIMMgr::INVITATION_TYPE_INSTANT_MESSAGE));
1402 } 1572 }
1403 } //end if invitation has instant message 1573 } //end if invitation has instant message
1404 else if ( input["body"].has("voice") ) 1574 else if ( input["body"].has("voice") )
@@ -1419,7 +1589,18 @@ public:
1419 input["body"]["session_name"].asString(), 1589 input["body"]["session_name"].asString(),
1420 input["body"]["from_id"].asUUID(), 1590 input["body"]["from_id"].asUUID(),
1421 input["body"]["from_name"].asString(), 1591 input["body"]["from_name"].asString(),
1422 IM_SESSION_INVITE); 1592 IM_SESSION_INVITE,
1593 LLIMMgr::INVITATION_TYPE_VOICE);
1594 }
1595 else if ( input["body"].has("immediate") )
1596 {
1597 gIMMgr->inviteToSession(
1598 input["body"]["session_id"].asUUID(),
1599 input["body"]["session_name"].asString(),
1600 input["body"]["from_id"].asUUID(),
1601 input["body"]["from_name"].asString(),
1602 IM_SESSION_INVITE,
1603 LLIMMgr::INVITATION_TYPE_IMMEDIATE);
1423 } 1604 }
1424 } 1605 }
1425}; 1606};
@@ -1440,6 +1621,10 @@ LLHTTPRegistration<LLViewerChatterBoxSessionAgentListUpdates>
1440 gHTTPRegistrationMessageChatterboxsessionagentlistupdates( 1621 gHTTPRegistrationMessageChatterboxsessionagentlistupdates(
1441 "/message/ChatterBoxSessionAgentListUpdates"); 1622 "/message/ChatterBoxSessionAgentListUpdates");
1442 1623
1624LLHTTPRegistration<LLViewerChatterBoxSessionUpdate>
1625 gHTTPRegistrationMessageChatterBoxSessionUpdate(
1626 "/message/ChatterBoxSessionUpdate");
1627
1443LLHTTPRegistration<LLViewerChatterBoxInvitation> 1628LLHTTPRegistration<LLViewerChatterBoxInvitation>
1444 gHTTPRegistrationMessageChatterBoxInvitation( 1629 gHTTPRegistrationMessageChatterBoxInvitation(
1445 "/message/ChatterBoxInvitation"); 1630 "/message/ChatterBoxInvitation");