aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/linden/indra/newview/llimview.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'linden/indra/newview/llimview.cpp')
-rw-r--r--linden/indra/newview/llimview.cpp823
1 files changed, 513 insertions, 310 deletions
diff --git a/linden/indra/newview/llimview.cpp b/linden/indra/newview/llimview.cpp
index 111852d..9df51b9 100644
--- a/linden/indra/newview/llimview.cpp
+++ b/linden/indra/newview/llimview.cpp
@@ -1,5 +1,5 @@
1/** 1/**
2 * @file llimview.cpp 2 * @file LLIMMgr.cpp
3 * @brief Container for Instant Messaging 3 * @brief Container for Instant Messaging
4 * 4 *
5 * Copyright (c) 2001-2007, Linden Research, Inc. 5 * Copyright (c) 2001-2007, Linden Research, Inc.
@@ -32,9 +32,9 @@
32 32
33#include "llfontgl.h" 33#include "llfontgl.h"
34#include "llrect.h" 34#include "llrect.h"
35#include "lldbstrings.h"
36#include "llerror.h" 35#include "llerror.h"
37#include "llbutton.h" 36#include "llbutton.h"
37#include "llhttpclient.h"
38#include "llsdutil.h" 38#include "llsdutil.h"
39#include "llstring.h" 39#include "llstring.h"
40#include "linked_lists.h" 40#include "linked_lists.h"
@@ -46,8 +46,8 @@
46#include "llviewerwindow.h" 46#include "llviewerwindow.h"
47#include "llresmgr.h" 47#include "llresmgr.h"
48#include "llfloaterchat.h" 48#include "llfloaterchat.h"
49#include "llfloaterchatterbox.h"
49#include "llfloaternewim.h" 50#include "llfloaternewim.h"
50#include "llhttpclient.h"
51#include "llhttpnode.h" 51#include "llhttpnode.h"
52#include "llimpanel.h" 52#include "llimpanel.h"
53#include "llresizebar.h" 53#include "llresizebar.h"
@@ -62,40 +62,48 @@
62#include "llcallingcard.h" 62#include "llcallingcard.h"
63#include "lltoolbar.h" 63#include "lltoolbar.h"
64#include "llviewermessage.h" 64#include "llviewermessage.h"
65#include "llnotify.h"
65#include "llviewerregion.h" 66#include "llviewerregion.h"
66 67
68#include "llfirstuse.h"
69
67const EInstantMessage GROUP_DIALOG = IM_SESSION_GROUP_START; 70const EInstantMessage GROUP_DIALOG = IM_SESSION_GROUP_START;
68const EInstantMessage DEFAULT_DIALOG = IM_NOTHING_SPECIAL; 71const EInstantMessage DEFAULT_DIALOG = IM_NOTHING_SPECIAL;
69 72
70// 73//
71// Globals 74// Globals
72// 75//
73LLIMView* gIMView = NULL; 76LLIMMgr* gIMMgr = NULL;
74 77
75// 78//
76// Statics 79// Statics
77// 80//
81//*FIXME: make these all either UIStrings or Strings
78static LLString sOnlyUserMessage; 82static LLString sOnlyUserMessage;
79static LLString sOfflineMessage; 83static LLUIString sOfflineMessage;
80 84
81static std::map<std::string,LLString> sEventStringsMap; 85static std::map<std::string,LLString> sEventStringsMap;
82static std::map<std::string,LLString> sErrorStringsMap; 86static std::map<std::string,LLString> sErrorStringsMap;
83static std::map<std::string,LLString> sForceCloseSessionMap; 87static std::map<std::string,LLString> sForceCloseSessionMap;
88static LLUIString sInviteMessage;
84// 89//
85// Helper Functions 90// Helper Functions
86// 91//
87 92
88// returns true if a should appear before b 93// returns true if a should appear before b
89static BOOL group_dictionary_sort( LLGroupData* a, LLGroupData* b ) 94//static BOOL group_dictionary_sort( LLGroupData* a, LLGroupData* b )
90{ 95//{
91 return (LLString::compareDict( a->mName, b->mName ) < 0); 96// return (LLString::compareDict( a->mName, b->mName ) < 0);
92} 97//}
93 98
94 99
95// the other_participant_id is either an agent_id, a group_id, or an inventory 100// the other_participant_id is either an agent_id, a group_id, or an inventory
96// folder item_id (collection of calling cards) 101// folder item_id (collection of calling cards)
97static LLUUID compute_session_id(EInstantMessage dialog, 102
98 const LLUUID& other_participant_id) 103// static
104LLUUID LLIMMgr::computeSessionID(
105 EInstantMessage dialog,
106 const LLUUID& other_participant_id)
99{ 107{
100 LLUUID session_id; 108 LLUUID session_id;
101 if (IM_SESSION_GROUP_START == dialog) 109 if (IM_SESSION_GROUP_START == dialog)
@@ -107,6 +115,11 @@ static LLUUID compute_session_id(EInstantMessage dialog,
107 { 115 {
108 session_id.generate(); 116 session_id.generate();
109 } 117 }
118 else if (IM_SESSION_INVITE == dialog)
119 {
120 // use provided session id for invites
121 session_id = other_participant_id;
122 }
110 else 123 else
111 { 124 {
112 LLUUID agent_id = gAgent.getID(); 125 LLUUID agent_id = gAgent.getID();
@@ -131,88 +144,35 @@ static LLUUID compute_session_id(EInstantMessage dialog,
131 144
132LLFloaterIM::LLFloaterIM() 145LLFloaterIM::LLFloaterIM()
133{ 146{
147 // autoresize=false is necessary to avoid resizing of the IM window whenever
148 // a session is opened or closed (it would otherwise resize the window to match
149 // the size of the im-sesssion when they were created. This happens in
150 // LLMultiFloater::resizeToContents() when called through LLMultiFloater::addFloater())
151 this->mAutoResize = FALSE;
134 gUICtrlFactory->buildFloater(this, "floater_im.xml"); 152 gUICtrlFactory->buildFloater(this, "floater_im.xml");
135} 153}
136 154
137BOOL LLFloaterIM::postBuild() 155BOOL LLFloaterIM::postBuild()
138{ 156{
139 requires("only_user_message", WIDGET_TYPE_TEXT_BOX); 157 sOnlyUserMessage = getFormattedUIString("only_user_message");
140 requires("offline_message", WIDGET_TYPE_TEXT_BOX); 158 sOfflineMessage = getUIString("offline_message");
141 requires("generic_request_error", WIDGET_TYPE_TEXT_BOX);
142 requires("insufficient_perms_error", WIDGET_TYPE_TEXT_BOX);
143 requires("generic_request_error", WIDGET_TYPE_TEXT_BOX);
144 requires("add_session_event", WIDGET_TYPE_TEXT_BOX);
145 requires("message_session_event", WIDGET_TYPE_TEXT_BOX);
146 requires("removed_from_group", WIDGET_TYPE_TEXT_BOX);
147
148 if (checkRequirements())
149 {
150 sOnlyUserMessage = childGetText("only_user_message");
151 sOfflineMessage = childGetText("offline_message");
152
153 sErrorStringsMap["generic"] =
154 childGetText("generic_request_error");
155 sErrorStringsMap["unverified"] =
156 childGetText("insufficient_perms_error");
157 sErrorStringsMap["no_user_911"] =
158 childGetText("user_no_help");
159 159
160 sEventStringsMap["add"] = childGetText("add_session_event"); 160 sErrorStringsMap["generic"] =
161 sEventStringsMap["message"] = 161 getFormattedUIString("generic_request_error");
162 childGetText("message_session_event"); 162 sErrorStringsMap["unverified"] =
163 getFormattedUIString("insufficient_perms_error");
164 sErrorStringsMap["no_user_911"] =
165 getFormattedUIString("user_no_help");
163 166
164 sForceCloseSessionMap["removed"] = 167 sEventStringsMap["add"] = childGetText("add_session_event");
165 childGetText("removed_from_group"); 168 sEventStringsMap["message"] =
169 getFormattedUIString("message_session_event");
166 170
167 return TRUE; 171 sForceCloseSessionMap["removed"] =
168 } 172 getFormattedUIString("removed_from_group");
169 return FALSE;
170}
171
172//// virtual
173//BOOL LLFloaterIM::handleKeyHere(KEY key, MASK mask, BOOL called_from_parent)
174//{
175// BOOL handled = FALSE;
176// if (getEnabled()
177// && mask == (MASK_CONTROL|MASK_SHIFT))
178// {
179// if (key == 'W')
180// {
181// LLFloater* floater = getActiveFloater();
182// if (floater)
183// {
184// if (mTabContainer->getTabCount() == 1)
185// {
186// // trying to close last tab, close
187// // entire window.
188// close();
189// handled = TRUE;
190// }
191// }
192// }
193// }
194// return handled || LLMultiFloater::handleKeyHere(key, mask, called_from_parent);
195//}
196 173
197void LLFloaterIM::onClose(bool app_quitting) 174 sInviteMessage = getUIString("invite_message");
198{ 175 return TRUE;
199 if (!app_quitting)
200 {
201 gSavedSettings.setBOOL("ShowIM", FALSE);
202 }
203 setVisible(FALSE);
204}
205
206//virtual
207void LLFloaterIM::addFloater(LLFloater* floaterp, BOOL select_added_floater, LLTabContainer::eInsertionPoint insertion_point)
208{
209 // this code is needed to fix the bug where new IMs received will resize the IM floater.
210 // SL-29075, SL-24556, and others
211 LLRect parent_rect = getRect();
212 S32 dheight = LLFLOATER_HEADER_SIZE + TABCNTR_HEADER_HEIGHT;
213 LLRect rect(0, parent_rect.getHeight()-dheight, parent_rect.getWidth(), 0);
214 floaterp->reshape(rect.getWidth(), rect.getHeight(), TRUE);
215 LLMultiFloater::addFloater(floaterp, select_added_floater, insertion_point);
216} 176}
217 177
218//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 178//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -224,7 +184,7 @@ void LLFloaterIM::addFloater(LLFloater* floaterp, BOOL select_added_floater, LLT
224class LLIMViewFriendObserver : public LLFriendObserver 184class LLIMViewFriendObserver : public LLFriendObserver
225{ 185{
226public: 186public:
227 LLIMViewFriendObserver(LLIMView* tv) : mTV(tv) {} 187 LLIMViewFriendObserver(LLIMMgr* tv) : mTV(tv) {}
228 virtual ~LLIMViewFriendObserver() {} 188 virtual ~LLIMViewFriendObserver() {}
229 virtual void changed(U32 mask) 189 virtual void changed(U32 mask)
230 { 190 {
@@ -234,7 +194,30 @@ public:
234 } 194 }
235 } 195 }
236protected: 196protected:
237 LLIMView* mTV; 197 LLIMMgr* mTV;
198};
199
200
201class LLIMMgr::LLIMSessionInvite
202{
203public:
204 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) :
205 mSessionID(session_id),
206 mSessionName(session_name),
207 mCallerID(caller_id),
208 mCallerName(caller_name),
209 mType(type),
210 mSessionHandle(session_handle),
211 mNotifyBox(notify_box)
212 {};
213
214 LLUUID mSessionID;
215 LLString mSessionName;
216 LLUUID mCallerID;
217 LLString mCallerName;
218 EInstantMessage mType;
219 LLString mSessionHandle;
220 LLString mNotifyBox;
238}; 221};
239 222
240 223
@@ -245,7 +228,7 @@ protected:
245// This is a helper function to determine what kind of im session 228// This is a helper function to determine what kind of im session
246// should be used for the given agent. 229// should be used for the given agent.
247// static 230// static
248EInstantMessage LLIMView::defaultIMTypeForAgent(const LLUUID& agent_id) 231EInstantMessage LLIMMgr::defaultIMTypeForAgent(const LLUUID& agent_id)
249{ 232{
250 EInstantMessage type = IM_NOTHING_SPECIAL; 233 EInstantMessage type = IM_NOTHING_SPECIAL;
251 if(is_agent_friend(agent_id)) 234 if(is_agent_friend(agent_id))
@@ -259,20 +242,20 @@ EInstantMessage LLIMView::defaultIMTypeForAgent(const LLUUID& agent_id)
259} 242}
260 243
261// static 244// static
262//void LLIMView::onPinButton(void*) 245//void LLIMMgr::onPinButton(void*)
263//{ 246//{
264// BOOL state = gSavedSettings.getBOOL( "PinTalkViewOpen" ); 247// BOOL state = gSavedSettings.getBOOL( "PinTalkViewOpen" );
265// gSavedSettings.setBOOL( "PinTalkViewOpen", !state ); 248// gSavedSettings.setBOOL( "PinTalkViewOpen", !state );
266//} 249//}
267 250
268// static 251// static
269void LLIMView::toggle(void*) 252void LLIMMgr::toggle(void*)
270{ 253{
271 static BOOL return_to_mouselook = FALSE; 254 static BOOL return_to_mouselook = FALSE;
272 255
273 // Hide the button and show the floater or vice versa. 256 // Hide the button and show the floater or vice versa.
274 llassert( gIMView ); 257 llassert( gIMMgr );
275 BOOL old_state = gIMView->getFloaterOpen(); 258 BOOL old_state = gIMMgr->getFloaterOpen();
276 259
277 // If we're in mouselook and we triggered the Talk View, we want to talk. 260 // If we're in mouselook and we triggered the Talk View, we want to talk.
278 if( gAgent.cameraMouselook() && old_state ) 261 if( gAgent.cameraMouselook() && old_state )
@@ -303,53 +286,39 @@ void LLIMView::toggle(void*)
303 return_to_mouselook = FALSE; 286 return_to_mouselook = FALSE;
304 } 287 }
305 288
306 gIMView->setFloaterOpen( new_state ); 289 gIMMgr->setFloaterOpen( new_state );
307} 290}
308 291
309// 292//
310// Member Functions 293// Member Functions
311// 294//
312 295
313LLIMView::LLIMView(const std::string& name, const LLRect& rect) : 296LLIMMgr::LLIMMgr() :
314 LLView(name, rect, FALSE),
315 mFriendObserver(NULL), 297 mFriendObserver(NULL),
316 mIMReceived(FALSE) 298 mIMReceived(FALSE)
317{ 299{
318 gIMView = this;
319 mFriendObserver = new LLIMViewFriendObserver(this); 300 mFriendObserver = new LLIMViewFriendObserver(this);
320 LLAvatarTracker::instance().addObserver(mFriendObserver); 301 LLAvatarTracker::instance().addObserver(mFriendObserver);
321 302
322 mTalkFloater = new LLFloaterIM(); 303 //*HACK: use floater to initialize string constants from xml file
304 // then delete it right away
305 LLFloaterIM* dummy_floater = new LLFloaterIM();
306 delete dummy_floater;
323 307
324 // New IM Panel 308 mPendingVoiceInvitations = LLSD::emptyMap();
325 mNewIMFloater = new LLFloaterNewIM();
326 mTalkFloater->addFloater(mNewIMFloater, TRUE);
327
328 // Tabs sometimes overlap resize handle
329 mTalkFloater->moveResizeHandleToFront();
330} 309}
331 310
332LLIMView::~LLIMView() 311LLIMMgr::~LLIMMgr()
333{ 312{
334 LLAvatarTracker::instance().removeObserver(mFriendObserver); 313 LLAvatarTracker::instance().removeObserver(mFriendObserver);
335 delete mFriendObserver; 314 delete mFriendObserver;
336 // Children all cleaned up by default view destructor. 315 // Children all cleaned up by default view destructor.
337} 316}
338 317
339EWidgetType LLIMView::getWidgetType() const
340{
341 return WIDGET_TYPE_TALK_VIEW;
342}
343
344LLString LLIMView::getWidgetTag() const
345{
346 return LL_TALK_VIEW_TAG;
347}
348
349// Add a message to a session. 318// Add a message to a session.
350void LLIMView::addMessage( 319void LLIMMgr::addMessage(
351 const LLUUID& session_id, 320 const LLUUID& session_id,
352 const LLUUID& other_participant_id, 321 const LLUUID& target_id,
353 const char* from, 322 const char* from,
354 const char* msg, 323 const char* msg,
355 const char* session_name, 324 const char* session_name,
@@ -358,11 +327,30 @@ void LLIMView::addMessage(
358 const LLUUID& region_id, 327 const LLUUID& region_id,
359 const LLVector3& position) 328 const LLVector3& position)
360{ 329{
330 LLUUID other_participant_id = target_id;
331 bool is_from_system = target_id.isNull();
332
333 // don't process muted IMs
334 if (gMuteListp->isMuted(
335 other_participant_id,
336 LLMute::flagTextChat) && !gMuteListp->isLinden(from))
337 {
338 return;
339 }
340
341 //not sure why...but if it is from ourselves we set the target_id
342 //to be NULL
343 if( other_participant_id == gAgent.getID() )
344 {
345 other_participant_id = LLUUID::null;
346 }
347
361 LLFloaterIMPanel* floater; 348 LLFloaterIMPanel* floater;
362 LLUUID new_session_id = session_id; 349 LLUUID new_session_id = session_id;
363 if (new_session_id.isNull()) 350 if (new_session_id.isNull())
364 { 351 {
365 new_session_id = compute_session_id(dialog, other_participant_id); 352 //no session ID...compute new one
353 new_session_id = computeSessionID(dialog, other_participant_id);
366 } 354 }
367 floater = findFloaterBySession(new_session_id); 355 floater = findFloaterBySession(new_session_id);
368 if (!floater) 356 if (!floater)
@@ -374,20 +362,10 @@ void LLIMView::addMessage(
374 << " by participant " << other_participant_id << llendl; 362 << " by participant " << other_participant_id << llendl;
375 } 363 }
376 } 364 }
377 if(floater)
378 {
379 floater->addHistoryLine(msg);
380 }
381 else
382 {
383 //if we have recently requsted to be dropped from a session
384 //but are still receiving messages from the session, don't make
385 //a new floater
386 if ( mSessionsDropRequested.has(session_id.asString()) )
387 {
388 return ;
389 }
390 365
366 // create IM window as necessary
367 if(!floater)
368 {
391 const char* name = from; 369 const char* name = from;
392 if(session_name && (strlen(session_name)>1)) 370 if(session_name && (strlen(session_name)>1))
393 { 371 {
@@ -395,7 +373,12 @@ void LLIMView::addMessage(
395 } 373 }
396 374
397 375
398 floater = createFloater(new_session_id, other_participant_id, name, dialog, FALSE); 376 floater = createFloater(
377 new_session_id,
378 other_participant_id,
379 name,
380 dialog,
381 FALSE);
399 382
400 // When we get a new IM, and if you are a god, display a bit 383 // When we get a new IM, and if you are a god, display a bit
401 // of information about the source. This is to help liaisons 384 // of information about the source. This is to help liaisons
@@ -415,27 +398,41 @@ void LLIMView::addMessage(
415 //<< "*** region_id: " << region_id << std::endl 398 //<< "*** region_id: " << region_id << std::endl
416 //<< "*** position: " << position << std::endl; 399 //<< "*** position: " << position << std::endl;
417 400
418 floater->addHistoryLine(bonus_info.str()); 401 floater->addHistoryLine(bonus_info.str(), gSavedSettings.getColor4("SystemChatColor"));
419 } 402 }
420 403
421 floater->addHistoryLine(msg);
422 make_ui_sound("UISndNewIncomingIMSession"); 404 make_ui_sound("UISndNewIncomingIMSession");
423 } 405 }
424 406
425 if( !mTalkFloater->getVisible() && !floater->getVisible()) 407 // now add message to floater
408 if ( is_from_system ) // chat came from system
409 {
410 floater->addHistoryLine(
411 other_participant_id,
412 msg,
413 gSavedSettings.getColor4("SystemChatColor"));
414 }
415 else
416 {
417 floater->addHistoryLine(other_participant_id, msg);
418 }
419
420 LLFloaterChatterBox* chat_floater = LLFloaterChatterBox::getInstance(LLSD());
421
422 if( !chat_floater->getVisible() && !floater->getVisible())
426 { 423 {
427 //if the IM window is not open and the floater is not visible (i.e. not torn off) 424 //if the IM window is not open and the floater is not visible (i.e. not torn off)
428 LLFloater* previouslyActiveFloater = mTalkFloater->getActiveFloater(); 425 LLFloater* previouslyActiveFloater = chat_floater->getActiveFloater();
429 426
430 // select the newly added floater (or the floater with the new line added to it). 427 // select the newly added floater (or the floater with the new line added to it).
431 // it should be there. 428 // it should be there.
432 mTalkFloater->selectFloater(floater); 429 chat_floater->selectFloater(floater);
433 430
434 //there was a previously unseen IM, make that old tab flashing 431 //there was a previously unseen IM, make that old tab flashing
435 //it is assumed that the most recently unseen IM tab is the one current selected/active 432 //it is assumed that the most recently unseen IM tab is the one current selected/active
436 if ( previouslyActiveFloater && getIMReceived() ) 433 if ( previouslyActiveFloater && getIMReceived() )
437 { 434 {
438 mTalkFloater->setFloaterFlashing(previouslyActiveFloater, TRUE); 435 chat_floater->setFloaterFlashing(previouslyActiveFloater, TRUE);
439 } 436 }
440 437
441 //notify of a new IM 438 //notify of a new IM
@@ -443,37 +440,87 @@ void LLIMView::addMessage(
443 } 440 }
444} 441}
445 442
446void LLIMView::notifyNewIM() 443void LLIMMgr::addSystemMessage(const LLUUID& session_id, const LLString& message_name, const LLString::format_map_t& args)
444{
445 LLUIString message;
446
447 // null session id means near me (chat history)
448 if (session_id.isNull())
449 {
450 LLFloaterChat* floaterp = LLFloaterChat::getInstance();
451
452 message = floaterp->getUIString(message_name);
453 message.setArgList(args);
454
455 LLChat chat(message);
456 chat.mSourceType = CHAT_SOURCE_SYSTEM;
457 LLFloaterChat::getInstance()->addChatHistory(chat);
458 }
459 else // going to IM session
460 {
461 LLFloaterIMPanel* floaterp = findFloaterBySession(session_id);
462 if (floaterp)
463 {
464 message = floaterp->getUIString(message_name);
465 message.setArgList(args);
466
467 gIMMgr->addMessage(session_id, LLUUID::null, SYSTEM_FROM, message.getString().c_str());
468 }
469 }
470}
471
472void LLIMMgr::notifyNewIM()
447{ 473{
448 if(!gIMView->getFloaterOpen()) 474 if(!gIMMgr->getFloaterOpen())
449 { 475 {
450 mIMReceived = TRUE; 476 mIMReceived = TRUE;
451 } 477 }
452} 478}
453 479
454BOOL LLIMView::getIMReceived() const 480void LLIMMgr::clearNewIMNotification()
481{
482 mIMReceived = FALSE;
483}
484
485BOOL LLIMMgr::getIMReceived() const
455{ 486{
456 return mIMReceived; 487 return mIMReceived;
457} 488}
458 489
459// This method returns TRUE if the local viewer has a session 490// This method returns TRUE if the local viewer has a session
460// currently open keyed to the uuid. 491// currently open keyed to the uuid.
461BOOL LLIMView::isIMSessionOpen(const LLUUID& uuid) 492BOOL LLIMMgr::isIMSessionOpen(const LLUUID& uuid)
462{ 493{
463 LLFloaterIMPanel* floater = findFloaterBySession(uuid); 494 LLFloaterIMPanel* floater = findFloaterBySession(uuid);
464 if(floater) return TRUE; 495 if(floater) return TRUE;
465 return FALSE; 496 return FALSE;
466} 497}
467 498
499LLUUID LLIMMgr::addP2PSession(const std::string& name,
500 const LLUUID& other_participant_id,
501 const LLString& voice_session_handle)
502{
503 LLUUID session_id = addSession(name, IM_NOTHING_SPECIAL, other_participant_id);
504
505 LLFloaterIMPanel* floater = findFloaterBySession(session_id);
506 if(floater)
507 {
508 LLVoiceChannelP2P* voice_channelp = (LLVoiceChannelP2P*)floater->getVoiceChannel();
509 voice_channelp->setSessionHandle(voice_session_handle);
510 }
511
512 return session_id;
513}
514
468// This adds a session to the talk view. The name is the local name of 515// This adds a session to the talk view. The name is the local name of
469// the session, dialog specifies the type of session. If the session 516// the session, dialog specifies the type of session. If the session
470// exists, it is brought forward. Specifying id = NULL results in an 517// exists, it is brought forward. Specifying id = NULL results in an
471// im session to everyone. Returns the uuid of the session. 518// im session to everyone. Returns the uuid of the session.
472LLUUID LLIMView::addSession(const std::string& name, 519LLUUID LLIMMgr::addSession(const std::string& name,
473 EInstantMessage dialog, 520 EInstantMessage dialog,
474 const LLUUID& other_participant_id) 521 const LLUUID& other_participant_id)
475{ 522{
476 LLUUID session_id = compute_session_id(dialog, other_participant_id); 523 LLUUID session_id = computeSessionID(dialog, other_participant_id);
477 524
478 LLFloaterIMPanel* floater = findFloaterBySession(session_id); 525 LLFloaterIMPanel* floater = findFloaterBySession(session_id);
479 if(!floater) 526 if(!floater)
@@ -489,7 +536,7 @@ LLUUID LLIMView::addSession(const std::string& name,
489 TRUE); 536 TRUE);
490 537
491 noteOfflineUsers(floater, ids); 538 noteOfflineUsers(floater, ids);
492 mTalkFloater->showFloater(floater); 539 LLFloaterChatterBox::getInstance(LLSD())->showFloater(floater);
493 } 540 }
494 else 541 else
495 { 542 {
@@ -502,7 +549,7 @@ LLUUID LLIMView::addSession(const std::string& name,
502 549
503// Adds a session using the given session_id. If the session already exists 550// Adds a session using the given session_id. If the session already exists
504// the dialog type is assumed correct. Returns the uuid of the session. 551// the dialog type is assumed correct. Returns the uuid of the session.
505LLUUID LLIMView::addSession(const std::string& name, 552LLUUID LLIMMgr::addSession(const std::string& name,
506 EInstantMessage dialog, 553 EInstantMessage dialog,
507 const LLUUID& other_participant_id, 554 const LLUUID& other_participant_id,
508 const LLDynamicArray<LLUUID>& ids) 555 const LLDynamicArray<LLUUID>& ids)
@@ -512,7 +559,7 @@ LLUUID LLIMView::addSession(const std::string& name,
512 return LLUUID::null; 559 return LLUUID::null;
513 } 560 }
514 561
515 LLUUID session_id = compute_session_id(dialog, 562 LLUUID session_id = computeSessionID(dialog,
516 other_participant_id); 563 other_participant_id);
517 564
518 LLFloaterIMPanel* floater = findFloaterBySession(session_id); 565 LLFloaterIMPanel* floater = findFloaterBySession(session_id);
@@ -531,7 +578,7 @@ LLUUID LLIMView::addSession(const std::string& name,
531 578
532 noteOfflineUsers(floater, ids); 579 noteOfflineUsers(floater, ids);
533 } 580 }
534 mTalkFloater->showFloater(floater); 581 LLFloaterChatterBox::getInstance(LLSD())->showFloater(floater);
535 //mTabContainer->selectTabPanel(panel); 582 //mTabContainer->selectTabPanel(panel);
536 floater->setInputFocus(TRUE); 583 floater->setInputFocus(TRUE);
537 return floater->getSessionID(); 584 return floater->getSessionID();
@@ -539,134 +586,272 @@ LLUUID LLIMView::addSession(const std::string& name,
539 586
540// This removes the panel referenced by the uuid, and then restores 587// This removes the panel referenced by the uuid, and then restores
541// internal consistency. The internal pointer is not deleted. 588// internal consistency. The internal pointer is not deleted.
542void LLIMView::removeSession(const LLUUID& session_id) 589void LLIMMgr::removeSession(const LLUUID& session_id)
543{ 590{
544 LLFloaterIMPanel* floater = findFloaterBySession(session_id); 591 LLFloaterIMPanel* floater = findFloaterBySession(session_id);
545 if(floater) 592 if(floater)
546 { 593 {
547 mFloaters.erase(floater->getHandle()); 594 mFloaters.erase(floater->getHandle());
548 mTalkFloater->removeFloater(floater); 595 LLFloaterChatterBox::getInstance(LLSD())->removeFloater(floater);
549 //mTabContainer->removeTabPanel(floater); 596 //mTabContainer->removeTabPanel(floater);
550 } 597 }
551
552 if ( session_id.notNull() && floater->getDialogType() != IM_NOTHING_SPECIAL )
553 {
554 mSessionsDropRequested[session_id.asString()] = LLSD();
555 }
556} 598}
557 599
558void LLIMView::refresh() 600void LLIMMgr::inviteToSession(
601 const LLUUID& session_id,
602 const LLString& session_name,
603 const LLUUID& caller_id,
604 const LLString& caller_name,
605 EInstantMessage type,
606 const LLString& session_handle)
559{ 607{
560 S32 old_scroll_pos = mNewIMFloater->getScrollPos(); 608 //ignore voice invites from voice-muted residents
561 mNewIMFloater->clearAllTargets(); 609 if (gMuteListp->isMuted(caller_id))
610 {
611 return;
612 }
562 613
563 // build a list of groups. 614 LLString notify_box_type;
564 LLLinkedList<LLGroupData> group_list( group_dictionary_sort );
565 615
566 LLGroupData* group; 616 BOOL ad_hoc_invite = FALSE;
567 S32 count = gAgent.mGroups.count(); 617 if(type == IM_SESSION_P2P_INVITE)
568 S32 i;
569 // read/sort groups on the first pass.
570 for(i = 0; i < count; ++i)
571 { 618 {
572 group = &(gAgent.mGroups.get(i)); 619 notify_box_type = "VoiceInviteP2P";
573 group_list.addDataSorted( group );
574 } 620 }
575 621 else if (gAgent.isInGroup(session_id))
576 // add groups to the floater on the second pass. 622 {
577 for(group = group_list.getFirstData(); 623 notify_box_type = "VoiceInviteGroup";
578 group; 624 }
579 group = group_list.getNextData()) 625 else
580 { 626 {
581 mNewIMFloater->addGroup(group->mID, (void*)(&GROUP_DIALOG), TRUE, FALSE); 627 notify_box_type = "VoiceInviteAdHoc";
628 ad_hoc_invite = TRUE;
582 } 629 }
583 630
584 // build a set of buddies in the current buddy list. 631 LLIMSessionInvite* invite = new LLIMSessionInvite(
585 LLCollectAllBuddies collector; 632 session_id,
586 LLAvatarTracker::instance().applyFunctor(collector); 633 session_name,
587 LLCollectAllBuddies::buddy_map_t::iterator it; 634 caller_id,
588 LLCollectAllBuddies::buddy_map_t::iterator end; 635 caller_name,
589 it = collector.mOnline.begin(); 636 type,
590 end = collector.mOnline.end(); 637 session_handle,
591 for( ; it != end; ++it) 638 notify_box_type);
639
640 LLVoiceChannel* channelp = LLVoiceChannel::getChannelByID(session_id);
641 if (channelp && channelp->callStarted())
592 { 642 {
593 mNewIMFloater->addAgent((*it).second, (void*)(&DEFAULT_DIALOG), TRUE); 643 // you have already started a call to the other user, so just accept the invite
644 inviteUserResponse(0, invite);
645 return;
594 } 646 }
595 it = collector.mOffline.begin(); 647
596 end = collector.mOffline.end(); 648 if (type == IM_SESSION_P2P_INVITE || ad_hoc_invite)
597 for( ; it != end; ++it)
598 { 649 {
599 mNewIMFloater->addAgent((*it).second, (void*)(&DEFAULT_DIALOG), FALSE); 650 // is the inviter a friend?
651 if (LLAvatarTracker::instance().getBuddyInfo(caller_id) == NULL)
652 {
653 // if not, and we are ignoring voice invites from non-friends
654 // then silently decline
655 if (gSavedSettings.getBOOL("VoiceCallsFriendsOnly"))
656 {
657 // invite not from a friend, so decline
658 inviteUserResponse(1, invite);
659 return;
660 }
661 }
600 } 662 }
601 663
602 mNewIMFloater->setScrollPos( old_scroll_pos ); 664 if ( !mPendingVoiceInvitations.has(session_id.asString()) )
665 {
666 if (caller_name.empty())
667 {
668 gCacheName->getName(caller_id, onInviteNameLookup, invite);
669 }
670 else
671 {
672 LLString::format_map_t args;
673 args["[NAME]"] = caller_name;
674 args["[GROUP]"] = session_name;
675
676 LLNotifyBox::showXml(notify_box_type,
677 args,
678 inviteUserResponse,
679 (void*)invite);
680
681 }
682 mPendingVoiceInvitations[session_id.asString()] = LLSD();
683 }
603} 684}
604 685
605// JC - This used to set console visibility. It doesn't any more. 686//static
606void LLIMView::setFloaterOpen(BOOL set_open) 687void LLIMMgr::onInviteNameLookup(const LLUUID& id, const char* first, const char* last, BOOL is_group, void* userdata)
607{ 688{
608 gSavedSettings.setBOOL("ShowIM", set_open); 689 LLIMSessionInvite* invite = (LLIMSessionInvite*)userdata;
609 690
610 //RN "visible" and "open" are considered synonomous for now 691 invite->mCallerName = llformat("%s %s", first, last);
611 if (set_open) 692 invite->mSessionName = invite->mCallerName;
693
694 LLString::format_map_t args;
695 args["[NAME]"] = invite->mCallerName;
696
697 LLNotifyBox::showXml(invite->mNotifyBox,
698 args,
699 inviteUserResponse,
700 (void*)invite);
701}
702
703class LLViewerChatterBoxInvitationAcceptResponder :
704 public LLHTTPClient::Responder
705{
706public:
707 LLViewerChatterBoxInvitationAcceptResponder(
708 const LLUUID& session_id,
709 bool is_voice_invitation)
612 { 710 {
613 mTalkFloater->open(); /*Flawfinder: ignore*/ 711 mSessionID = session_id;
712 mIsVoiceInvitiation = is_voice_invitation;
614 } 713 }
615 else 714
715 void result(const LLSD& content)
616 { 716 {
617 mTalkFloater->close(); 717 if ( gIMMgr)
718 {
719 LLFloaterIMPanel* floaterp =
720 gIMMgr->findFloaterBySession(mSessionID);
721
722 if (floaterp)
723 {
724 floaterp->setSpeakersList(content["agents"]);
725
726 if ( mIsVoiceInvitiation )
727 {
728 floaterp->requestAutoConnect();
729 LLFloaterIMPanel::onClickStartCall(floaterp);
730 }
731 }
732
733 if ( mIsVoiceInvitiation )
734 {
735 gIMMgr->clearPendingVoiceInviation(mSessionID);
736 }
737 }
618 } 738 }
619 739
620 if( set_open ) 740 void error(U32 statusNum, const std::string& reason)
621 { 741 {
622 // notifyNewIM(); 742 //throw something back to the viewer here?
623 743 if ( gIMMgr && mIsVoiceInvitiation )
624 // We're showing the IM, so mark view as non-pending 744 {
625 mIMReceived = FALSE; 745 gIMMgr->clearPendingVoiceInviation(mSessionID);
746 }
626 } 747 }
627}
628 748
749private:
750 LLUUID mSessionID;
751 bool mIsVoiceInvitiation;
752};
629 753
630BOOL LLIMView::getFloaterOpen() 754//static
631{ 755void LLIMMgr::inviteUserResponse(S32 option, void* user_data)
632 return mTalkFloater->getVisible();
633}
634
635void LLIMView::pruneSessions()
636{ 756{
637 if(mNewIMFloater) 757 LLIMSessionInvite* invitep = (LLIMSessionInvite*)user_data;
758
759 switch(option)
638 { 760 {
639 BOOL removed = TRUE; 761 case 0: // accept
640 LLFloaterIMPanel* floater = NULL; 762 {
641 while(removed) 763 if (invitep->mType == IM_SESSION_P2P_INVITE)
764 {
765 // create a normal IM session
766 invitep->mSessionID = gIMMgr->addP2PSession(
767 invitep->mSessionName,
768 invitep->mCallerID,
769 invitep->mSessionHandle);
770
771 LLFloaterIMPanel* im_floater =
772 gIMMgr->findFloaterBySession(
773 invitep->mSessionID);
774 if (im_floater)
775 {
776 im_floater->requestAutoConnect();
777 LLFloaterIMPanel::onClickStartCall(im_floater);
778 }
779
780 gIMMgr->clearPendingVoiceInviation(invitep->mSessionID);
781 }
782 else
783 {
784 gIMMgr->addSession(
785 invitep->mSessionName,
786 invitep->mType,
787 invitep->mSessionID);
788
789 std::string url = gAgent.getRegion()->getCapability(
790 "ChatSessionRequest");
791
792 LLSD data;
793 data["method"] = "accept invitation";
794 data["session-id"] = invitep->mSessionID;
795 LLHTTPClient::post(
796 url,
797 data,
798 new LLViewerChatterBoxInvitationAcceptResponder(
799 invitep->mSessionID,
800 true));
801 }
802 }
803 break;
804 case 2: // mute (also implies ignore, so this falls through to the "ignore" case below)
805 {
806 // mute the sender of this invite
807 if (!gMuteListp->isMuted(invitep->mCallerID))
808 {
809 LLMute mute(invitep->mCallerID, invitep->mCallerName, LLMute::AGENT);
810 gMuteListp->add(mute);
811 }
812 }
813 /* FALLTHROUGH */
814
815 case 1: // ignore
642 { 816 {
643 removed = FALSE; 817 if (invitep->mType == IM_SESSION_P2P_INVITE)
644 std::set<LLViewHandle>::iterator handle_it;
645 for(handle_it = mFloaters.begin();
646 handle_it != mFloaters.end();
647 ++handle_it)
648 { 818 {
649 floater = (LLFloaterIMPanel*)LLFloater::getFloaterByHandle(*handle_it); 819 if(gVoiceClient)
650 if(floater && !mNewIMFloater->isUUIDAvailable(floater->getOtherParticipantID()))
651 { 820 {
652 // remove this floater 821 gVoiceClient->declineInvite(invitep->mSessionHandle);
653 removed = TRUE;
654 mFloaters.erase(handle_it++);
655 floater->close();
656 break;
657 } 822 }
658 } 823 }
659 } 824 }
825 break;
660 } 826 }
827
828 delete invitep;
661} 829}
662 830
831void LLIMMgr::refresh()
832{
833}
663 834
664void LLIMView::disconnectAllSessions() 835void LLIMMgr::setFloaterOpen(BOOL set_open)
665{ 836{
666 if(mNewIMFloater) 837 if (set_open)
667 { 838 {
668 mNewIMFloater->setEnabled(FALSE); 839 LLFloaterChatterBox::showInstance(LLSD());
669 } 840 }
841 else
842 {
843 LLFloaterChatterBox::hideInstance(LLSD());
844 }
845}
846
847
848BOOL LLIMMgr::getFloaterOpen()
849{
850 return LLFloaterChatterBox::instanceVisible(LLSD());
851}
852
853void LLIMMgr::disconnectAllSessions()
854{
670 LLFloaterIMPanel* floater = NULL; 855 LLFloaterIMPanel* floater = NULL;
671 std::set<LLViewHandle>::iterator handle_it; 856 std::set<LLViewHandle>::iterator handle_it;
672 for(handle_it = mFloaters.begin(); 857 for(handle_it = mFloaters.begin();
@@ -681,7 +866,7 @@ void LLIMView::disconnectAllSessions()
681 if (floater) 866 if (floater)
682 { 867 {
683 floater->setEnabled(FALSE); 868 floater->setEnabled(FALSE);
684 floater->onClose(TRUE); 869 floater->close(TRUE);
685 } 870 }
686 } 871 }
687} 872}
@@ -690,7 +875,7 @@ void LLIMView::disconnectAllSessions()
690// This method returns the im panel corresponding to the uuid 875// This method returns the im panel corresponding to the uuid
691// provided. The uuid can either be a session id or an agent 876// provided. The uuid can either be a session id or an agent
692// id. Returns NULL if there is no matching panel. 877// id. Returns NULL if there is no matching panel.
693LLFloaterIMPanel* LLIMView::findFloaterBySession(const LLUUID& session_id) 878LLFloaterIMPanel* LLIMMgr::findFloaterBySession(const LLUUID& session_id)
694{ 879{
695 LLFloaterIMPanel* rv = NULL; 880 LLFloaterIMPanel* rv = NULL;
696 std::set<LLViewHandle>::iterator handle_it; 881 std::set<LLViewHandle>::iterator handle_it;
@@ -709,17 +894,25 @@ LLFloaterIMPanel* LLIMView::findFloaterBySession(const LLUUID& session_id)
709} 894}
710 895
711 896
712BOOL LLIMView::hasSession(const LLUUID& session_id) 897BOOL LLIMMgr::hasSession(const LLUUID& session_id)
713{ 898{
714 return (findFloaterBySession(session_id) != NULL); 899 return (findFloaterBySession(session_id) != NULL);
715} 900}
716 901
902void LLIMMgr::clearPendingVoiceInviation(const LLUUID& session_id)
903{
904 if ( mPendingVoiceInvitations.has(session_id.asString()) )
905 {
906 mPendingVoiceInvitations.erase(session_id.asString());
907 }
908}
909
717 910
718// create a floater and update internal representation for 911// create a floater and update internal representation for
719// consistency. Returns the pointer, caller (the class instance since 912// consistency. Returns the pointer, caller (the class instance since
720// it is a private method) is not responsible for deleting the 913// it is a private method) is not responsible for deleting the
721// pointer. Add the floater to this but do not select it. 914// pointer. Add the floater to this but do not select it.
722LLFloaterIMPanel* LLIMView::createFloater( 915LLFloaterIMPanel* LLIMMgr::createFloater(
723 const LLUUID& session_id, 916 const LLUUID& session_id,
724 const LLUUID& other_participant_id, 917 const LLUUID& other_participant_id,
725 const std::string& session_label, 918 const std::string& session_label,
@@ -731,7 +924,7 @@ LLFloaterIMPanel* LLIMView::createFloater(
731 llwarns << "Creating LLFloaterIMPanel with null session ID" << llendl; 924 llwarns << "Creating LLFloaterIMPanel with null session ID" << llendl;
732 } 925 }
733 926
734 llinfos << "LLIMView::createFloater: from " << other_participant_id 927 llinfos << "LLIMMgr::createFloater: from " << other_participant_id
735 << " in session " << session_id << llendl; 928 << " in session " << session_id << llendl;
736 LLFloaterIMPanel* floater = new LLFloaterIMPanel(session_label, 929 LLFloaterIMPanel* floater = new LLFloaterIMPanel(session_label,
737 LLRect(), 930 LLRect(),
@@ -740,12 +933,12 @@ LLFloaterIMPanel* LLIMView::createFloater(
740 other_participant_id, 933 other_participant_id,
741 dialog); 934 dialog);
742 LLTabContainerCommon::eInsertionPoint i_pt = user_initiated ? LLTabContainerCommon::RIGHT_OF_CURRENT : LLTabContainerCommon::END; 935 LLTabContainerCommon::eInsertionPoint i_pt = user_initiated ? LLTabContainerCommon::RIGHT_OF_CURRENT : LLTabContainerCommon::END;
743 mTalkFloater->addFloater(floater, FALSE, i_pt); 936 LLFloaterChatterBox::getInstance(LLSD())->addFloater(floater, FALSE, i_pt);
744 mFloaters.insert(floater->getHandle()); 937 mFloaters.insert(floater->getHandle());
745 return floater; 938 return floater;
746} 939}
747 940
748LLFloaterIMPanel* LLIMView::createFloater( 941LLFloaterIMPanel* LLIMMgr::createFloater(
749 const LLUUID& session_id, 942 const LLUUID& session_id,
750 const LLUUID& other_participant_id, 943 const LLUUID& other_participant_id,
751 const std::string& session_label, 944 const std::string& session_label,
@@ -758,7 +951,7 @@ LLFloaterIMPanel* LLIMView::createFloater(
758 llwarns << "Creating LLFloaterIMPanel with null session ID" << llendl; 951 llwarns << "Creating LLFloaterIMPanel with null session ID" << llendl;
759 } 952 }
760 953
761 llinfos << "LLIMView::createFloater: from " << other_participant_id 954 llinfos << "LLIMMgr::createFloater: from " << other_participant_id
762 << " in session " << session_id << llendl; 955 << " in session " << session_id << llendl;
763 LLFloaterIMPanel* floater = new LLFloaterIMPanel(session_label, 956 LLFloaterIMPanel* floater = new LLFloaterIMPanel(session_label,
764 LLRect(), 957 LLRect(),
@@ -768,18 +961,18 @@ LLFloaterIMPanel* LLIMView::createFloater(
768 ids, 961 ids,
769 dialog); 962 dialog);
770 LLTabContainerCommon::eInsertionPoint i_pt = user_initiated ? LLTabContainerCommon::RIGHT_OF_CURRENT : LLTabContainerCommon::END; 963 LLTabContainerCommon::eInsertionPoint i_pt = user_initiated ? LLTabContainerCommon::RIGHT_OF_CURRENT : LLTabContainerCommon::END;
771 mTalkFloater->addFloater(floater, FALSE, i_pt); 964 LLFloaterChatterBox::getInstance(LLSD())->addFloater(floater, FALSE, i_pt);
772 mFloaters.insert(floater->getHandle()); 965 mFloaters.insert(floater->getHandle());
773 return floater; 966 return floater;
774} 967}
775 968
776void LLIMView::noteOfflineUsers(LLFloaterIMPanel* floater, 969void LLIMMgr::noteOfflineUsers(LLFloaterIMPanel* floater,
777 const LLDynamicArray<LLUUID>& ids) 970 const LLDynamicArray<LLUUID>& ids)
778{ 971{
779 S32 count = ids.count(); 972 S32 count = ids.count();
780 if(count == 0) 973 if(count == 0)
781 { 974 {
782 floater->addHistoryLine(sOnlyUserMessage); 975 floater->addHistoryLine(sOnlyUserMessage, gSavedSettings.getColor4("SystemChatColor"));
783 } 976 }
784 else 977 else
785 { 978 {
@@ -796,25 +989,25 @@ void LLIMView::noteOfflineUsers(LLFloaterIMPanel* floater,
796 LLUIString offline = sOfflineMessage; 989 LLUIString offline = sOfflineMessage;
797 offline.setArg("[FIRST]", first); 990 offline.setArg("[FIRST]", first);
798 offline.setArg("[LAST]", last); 991 offline.setArg("[LAST]", last);
799 floater->addHistoryLine(offline); 992 floater->addHistoryLine(offline, gSavedSettings.getColor4("SystemChatColor"));
800 } 993 }
801 } 994 }
802 } 995 }
803} 996}
804 997
805void LLIMView::processIMTypingStart(const LLIMInfo* im_info) 998void LLIMMgr::processIMTypingStart(const LLIMInfo* im_info)
806{ 999{
807 processIMTypingCore(im_info, TRUE); 1000 processIMTypingCore(im_info, TRUE);
808} 1001}
809 1002
810void LLIMView::processIMTypingStop(const LLIMInfo* im_info) 1003void LLIMMgr::processIMTypingStop(const LLIMInfo* im_info)
811{ 1004{
812 processIMTypingCore(im_info, FALSE); 1005 processIMTypingCore(im_info, FALSE);
813} 1006}
814 1007
815void LLIMView::processIMTypingCore(const LLIMInfo* im_info, BOOL typing) 1008void LLIMMgr::processIMTypingCore(const LLIMInfo* im_info, BOOL typing)
816{ 1009{
817 LLUUID session_id = compute_session_id(im_info->mIMType, im_info->mFromID); 1010 LLUUID session_id = computeSessionID(im_info->mIMType, im_info->mFromID);
818 LLFloaterIMPanel* floater = findFloaterBySession(session_id); 1011 LLFloaterIMPanel* floater = findFloaterBySession(session_id);
819 if (floater) 1012 if (floater)
820 { 1013 {
@@ -822,8 +1015,9 @@ void LLIMView::processIMTypingCore(const LLIMInfo* im_info, BOOL typing)
822 } 1015 }
823} 1016}
824 1017
825void LLIMView::updateFloaterSessionID(const LLUUID& old_session_id, 1018void LLIMMgr::updateFloaterSessionID(
826 const LLUUID& new_session_id) 1019 const LLUUID& old_session_id,
1020 const LLUUID& new_session_id)
827{ 1021{
828 LLFloaterIMPanel* floater = findFloaterBySession(old_session_id); 1022 LLFloaterIMPanel* floater = findFloaterBySession(old_session_id);
829 if (floater) 1023 if (floater)
@@ -832,9 +1026,9 @@ void LLIMView::updateFloaterSessionID(const LLUUID& old_session_id,
832 } 1026 }
833} 1027}
834 1028
835void LLIMView::onDropRequestReplyReceived(const LLUUID& session_id) 1029LLFloaterChatterBox* LLIMMgr::getFloater()
836{ 1030{
837 mSessionsDropRequested.erase(session_id.asString()); 1031 return LLFloaterChatterBox::getInstance(LLSD());
838} 1032}
839 1033
840void onConfirmForceCloseError(S32 option, void* data) 1034void onConfirmForceCloseError(S32 option, void* data)
@@ -842,25 +1036,24 @@ void onConfirmForceCloseError(S32 option, void* data)
842 //only 1 option really 1036 //only 1 option really
843 LLFloaterIMPanel* floater = ((LLFloaterIMPanel*) data); 1037 LLFloaterIMPanel* floater = ((LLFloaterIMPanel*) data);
844 1038
845 if ( floater ) floater->onClose(FALSE); 1039 if ( floater ) floater->close(FALSE);
846} 1040}
847 1041
848class LLViewerIMSessionStartReply : public LLHTTPNode 1042class LLViewerChatterBoxSessionStartReply : public LLHTTPNode
849{ 1043{
850public: 1044public:
851 virtual void describe(Description& desc) const 1045 virtual void describe(Description& desc) const
852 { 1046 {
853 desc.shortInfo("Used for receiving a reply to a request to initialize an IM session"); 1047 desc.shortInfo("Used for receiving a reply to a request to initialize an ChatterBox session");
854 desc.postAPI(); 1048 desc.postAPI();
855 desc.input( 1049 desc.input(
856 "{\"client_session_id\": UUID, \"session_id\": UUID, \"success\" boolean, \"reason\": string"); 1050 "{\"client_session_id\": UUID, \"session_id\": UUID, \"success\" boolean, \"reason\": string");
857 desc.source(__FILE__, __LINE__); 1051 desc.source(__FILE__, __LINE__);
858 } 1052 }
859 1053
860 virtual void post( 1054 virtual void post(ResponsePtr response,
861 ResponsePtr response, 1055 const LLSD& context,
862 const LLSD& context, 1056 const LLSD& input) const
863 const LLSD& input) const
864 { 1057 {
865 LLSD body; 1058 LLSD body;
866 LLUUID temp_session_id; 1059 LLUUID temp_session_id;
@@ -874,16 +1067,21 @@ public:
874 if ( success ) 1067 if ( success )
875 { 1068 {
876 session_id = body["session_id"].asUUID(); 1069 session_id = body["session_id"].asUUID();
877 gIMView->updateFloaterSessionID( 1070 gIMMgr->updateFloaterSessionID(
878 temp_session_id, 1071 temp_session_id,
879 session_id); 1072 session_id);
1073 LLFloaterIMPanel* floaterp = gIMMgr->findFloaterBySession(session_id);
1074 if (floaterp)
1075 {
1076 floaterp->setSpeakersList(body["agents"]);
1077 }
880 } 1078 }
881 else 1079 else
882 { 1080 {
883 //throw an error dialog and close the temp session's 1081 //throw an error dialog and close the temp session's
884 //floater 1082 //floater
885 LLFloaterIMPanel* floater = 1083 LLFloaterIMPanel* floater =
886 gIMView->findFloaterBySession(temp_session_id); 1084 gIMMgr->findFloaterBySession(temp_session_id);
887 if (floater) 1085 if (floater)
888 { 1086 {
889 LLString::format_map_t args; 1087 LLString::format_map_t args;
@@ -891,22 +1089,22 @@ public:
891 sErrorStringsMap[body["error"].asString()]; 1089 sErrorStringsMap[body["error"].asString()];
892 args["[RECIPIENT]"] = floater->getTitle(); 1090 args["[RECIPIENT]"] = floater->getTitle();
893 1091
894 gViewerWindow->alertXml( 1092 gViewerWindow->alertXml("ChatterBoxSessionStartError",
895 "IMSessionStartError", 1093 args,
896 args, 1094 onConfirmForceCloseError,
897 onConfirmForceCloseError, 1095 floater);
898 floater); 1096
899 } 1097 }
900 } 1098 }
901 } 1099 }
902}; 1100};
903 1101
904class LLViewerIMSessionEventReply : public LLHTTPNode 1102class LLViewerChatterBoxSessionEventReply : public LLHTTPNode
905{ 1103{
906public: 1104public:
907 virtual void describe(Description& desc) const 1105 virtual void describe(Description& desc) const
908 { 1106 {
909 desc.shortInfo("Used for receiving a reply to a IM session event"); 1107 desc.shortInfo("Used for receiving a reply to a ChatterBox session event");
910 desc.postAPI(); 1108 desc.postAPI();
911 desc.input( 1109 desc.input(
912 "{\"event\": string, \"reason\": string, \"success\": boolean, \"session_id\": UUID"); 1110 "{\"event\": string, \"reason\": string, \"success\": boolean, \"session_id\": UUID");
@@ -928,7 +1126,7 @@ public:
928 { 1126 {
929 //throw an error dialog 1127 //throw an error dialog
930 LLFloaterIMPanel* floater = 1128 LLFloaterIMPanel* floater =
931 gIMView->findFloaterBySession(session_id); 1129 gIMMgr->findFloaterBySession(session_id);
932 if (floater) 1130 if (floater)
933 { 1131 {
934 LLString::format_map_t args; 1132 LLString::format_map_t args;
@@ -938,14 +1136,14 @@ public:
938 sEventStringsMap[body["event"].asString()]; 1136 sEventStringsMap[body["event"].asString()];
939 args["[RECIPIENT]"] = floater->getTitle(); 1137 args["[RECIPIENT]"] = floater->getTitle();
940 1138
941 gViewerWindow->alertXml("IMSessionEventError", 1139 gViewerWindow->alertXml("ChatterBoxSessionEventError",
942 args); 1140 args);
943 } 1141 }
944 } 1142 }
945 } 1143 }
946}; 1144};
947 1145
948class LLViewerForceCloseIMSession: public LLHTTPNode 1146class LLViewerForceCloseChatterBoxSession: public LLHTTPNode
949{ 1147{
950public: 1148public:
951 virtual void post(ResponsePtr response, 1149 virtual void post(ResponsePtr response,
@@ -959,7 +1157,7 @@ public:
959 reason = input["body"]["reason"].asString(); 1157 reason = input["body"]["reason"].asString();
960 1158
961 LLFloaterIMPanel* floater = 1159 LLFloaterIMPanel* floater =
962 gIMView ->findFloaterBySession(session_id); 1160 gIMMgr ->findFloaterBySession(session_id);
963 1161
964 if ( floater ) 1162 if ( floater )
965 { 1163 {
@@ -968,7 +1166,7 @@ public:
968 args["[NAME]"] = floater->getTitle(); 1166 args["[NAME]"] = floater->getTitle();
969 args["[REASON]"] = sForceCloseSessionMap[reason]; 1167 args["[REASON]"] = sForceCloseSessionMap[reason];
970 1168
971 gViewerWindow->alertXml("ForceCloseIMSession", 1169 gViewerWindow->alertXml("ForceCloseChatterBoxSession",
972 args, 1170 args,
973 onConfirmForceCloseError, 1171 onConfirmForceCloseError,
974 floater); 1172 floater);
@@ -976,28 +1174,6 @@ public:
976 } 1174 }
977}; 1175};
978 1176
979class LLViewerIMSessionDropReply : public LLHTTPNode
980{
981public:
982 virtual void post(ResponsePtr response,
983 const LLSD& context,
984 const LLSD& input) const
985 {
986 LLUUID session_id;
987 bool success;
988
989 success = input["body"]["success"].asBoolean();
990 session_id = input["body"]["session_id"].asUUID();
991
992 if ( !success )
993 {
994 //throw an error alert?
995 }
996
997 gIMView->onDropRequestReplyReceived(session_id);
998 }
999};
1000
1001class LLViewerChatterBoxSessionAgentListUpdates : public LLHTTPNode 1177class LLViewerChatterBoxSessionAgentListUpdates : public LLHTTPNode
1002{ 1178{
1003public: 1179public:
@@ -1006,29 +1182,38 @@ public:
1006 const LLSD& context, 1182 const LLSD& context,
1007 const LLSD& input) const 1183 const LLSD& input) const
1008 { 1184 {
1185 LLFloaterIMPanel* floaterp = gIMMgr->findFloaterBySession(input["body"]["session_id"].asUUID());
1186 if (floaterp)
1187 {
1188 floaterp->updateSpeakersList(input["body"]["updates"]);
1189 }
1009 } 1190 }
1010}; 1191};
1011 1192
1012class LLViewerChatterBoxInvitation : public LLHTTPNode 1193class LLViewerChatterBoxInvitation : public LLHTTPNode
1013{ 1194{
1014public: 1195public:
1196
1015 virtual void post( 1197 virtual void post(
1016 ResponsePtr responder, 1198 ResponsePtr response,
1017 const LLSD& context, 1199 const LLSD& context,
1018 const LLSD& input) const 1200 const LLSD& input) const
1019 { 1201 {
1020 if ( input["body"].has("instantmessage") ) 1202 if ( input["body"].has("instantmessage") )
1021 { 1203 {
1204 LLString capability = input["body"]["capabilities"]["call"].asString();
1205
1022 LLSD message_params = 1206 LLSD message_params =
1023 input["body"]["instantmessage"]["message_params"]; 1207 input["body"]["instantmessage"]["message_params"];
1024 1208
1209 //do something here to have the IM invite behave
1210 //just like a normal IM
1025 //this is just replicated code from process_improved_im 1211 //this is just replicated code from process_improved_im
1026 //and should really go in it's own function -jwolk 1212 //and should really go in it's own function -jwolk
1027 if (gNoRender) 1213 if (gNoRender)
1028 { 1214 {
1029 return; 1215 return;
1030 } 1216 }
1031
1032 char buffer[DB_IM_MSG_BUF_SIZE * 2]; /* Flawfinder: ignore */ 1217 char buffer[DB_IM_MSG_BUF_SIZE * 2]; /* Flawfinder: ignore */
1033 LLChat chat; 1218 LLChat chat;
1034 1219
@@ -1043,7 +1228,11 @@ public:
1043 (time_t) message_params["timestamp"].asInteger(); 1228 (time_t) message_params["timestamp"].asInteger();
1044 1229
1045 BOOL is_busy = gAgent.getBusy(); 1230 BOOL is_busy = gAgent.getBusy();
1046 BOOL is_muted = gMuteListp->isMuted(from_id, name); 1231 BOOL is_muted = gMuteListp->isMuted(
1232 from_id,
1233 name.c_str(),
1234 LLMute::flagTextChat);
1235
1047 BOOL is_linden = gMuteListp->isLinden( 1236 BOOL is_linden = gMuteListp->isLinden(
1048 name.c_str()); 1237 name.c_str());
1049 char separator_string[3]=": "; /* Flawfinder: ignore */ 1238 char separator_string[3]=": "; /* Flawfinder: ignore */
@@ -1060,7 +1249,8 @@ public:
1060 chat.mMuted = is_muted && !is_linden; 1249 chat.mMuted = is_muted && !is_linden;
1061 chat.mFromID = from_id; 1250 chat.mFromID = from_id;
1062 chat.mFromName = name; 1251 chat.mFromName = name;
1063 if (!is_linden && is_busy) 1252
1253 if (!is_linden && (is_busy || is_muted))
1064 { 1254 {
1065 return; 1255 return;
1066 } 1256 }
@@ -1088,10 +1278,9 @@ public:
1088 BOOL is_this_agent = FALSE; 1278 BOOL is_this_agent = FALSE;
1089 if(from_id == gAgentID) 1279 if(from_id == gAgentID)
1090 { 1280 {
1091 from_id = LLUUID::null;
1092 is_this_agent = TRUE; 1281 is_this_agent = TRUE;
1093 } 1282 }
1094 gIMView->addMessage( 1283 gIMMgr->addMessage(
1095 session_id, 1284 session_id,
1096 from_id, 1285 from_id,
1097 name.c_str(), 1286 name.c_str(),
@@ -1113,11 +1302,7 @@ public:
1113 chat.mText = buffer; 1302 chat.mText = buffer;
1114 LLFloaterChat::addChat(chat, TRUE, is_this_agent); 1303 LLFloaterChat::addChat(chat, TRUE, is_this_agent);
1115 1304
1116 //if we succesfully accepted the invitation 1305 //K now we want to accept the invitation
1117 //send a message back down
1118
1119 //TODO - When availble, have this response just be part
1120 //of an automatic response system
1121 std::string url = gAgent.getRegion()->getCapability( 1306 std::string url = gAgent.getRegion()->getCapability(
1122 "ChatSessionRequest"); 1307 "ChatSessionRequest");
1123 1308
@@ -1129,28 +1314,46 @@ public:
1129 LLHTTPClient::post( 1314 LLHTTPClient::post(
1130 url, 1315 url,
1131 data, 1316 data,
1132 NULL); 1317 new LLViewerChatterBoxInvitationAcceptResponder(
1318 input["body"]["session_id"],
1319 false));
1133 } 1320 }
1134 } //end if invitation has instant message 1321 } //end if invitation has instant message
1322 else if ( input["body"].has("voice") )
1323 {
1324 if (gNoRender)
1325 {
1326 return;
1327 }
1328
1329 if(!LLVoiceClient::voiceEnabled())
1330 {
1331 // Don't display voice invites unless the user has voice enabled.
1332 return;
1333 }
1334
1335 gIMMgr->inviteToSession(
1336 input["body"]["session_id"].asUUID(),
1337 input["body"]["session_name"].asString(),
1338 input["body"]["from_id"].asUUID(),
1339 input["body"]["from_name"].asString(),
1340 IM_SESSION_INVITE);
1341 }
1135 } 1342 }
1136}; 1343};
1137 1344
1138LLHTTPRegistration<LLViewerIMSessionStartReply> 1345LLHTTPRegistration<LLViewerChatterBoxSessionStartReply>
1139 gHTTPRegistrationMessageImsessionstartreply( 1346 gHTTPRegistrationMessageChatterboxsessionstartreply(
1140 "/message/ChatterBoxSessionStartReply"); 1347 "/message/ChatterBoxSessionStartReply");
1141 1348
1142LLHTTPRegistration<LLViewerIMSessionEventReply> 1349LLHTTPRegistration<LLViewerChatterBoxSessionEventReply>
1143 gHTTPRegistrationMessageImsessioneventreply( 1350 gHTTPRegistrationMessageChatterboxsessioneventreply(
1144 "/message/ChatterBoxSessionEventReply"); 1351 "/message/ChatterBoxSessionEventReply");
1145 1352
1146LLHTTPRegistration<LLViewerForceCloseIMSession> 1353LLHTTPRegistration<LLViewerForceCloseChatterBoxSession>
1147 gHTTPRegistrationMessageForceCloseImSession( 1354 gHTTPRegistrationMessageForceclosechatterboxsession(
1148 "/message/ForceCloseChatterBoxSession"); 1355 "/message/ForceCloseChatterBoxSession");
1149 1356
1150LLHTTPRegistration<LLViewerIMSessionDropReply>
1151 gHTTPRegistrationMessageImSessionDropReply(
1152 "/message/ChatterBoxSessionLeaveReply");
1153
1154LLHTTPRegistration<LLViewerChatterBoxSessionAgentListUpdates> 1357LLHTTPRegistration<LLViewerChatterBoxSessionAgentListUpdates>
1155 gHTTPRegistrationMessageChatterboxsessionagentlistupdates( 1358 gHTTPRegistrationMessageChatterboxsessionagentlistupdates(
1156 "/message/ChatterBoxSessionAgentListUpdates"); 1359 "/message/ChatterBoxSessionAgentListUpdates");