Create Conversation class, use it instead of Contact for chats

This is a commit with it's foot in a lot of places, but:

The Conversation class was created as the abstraction of chats: All
ImMessages that are relevant to a conversation get routed through it,
meta-data on chats is stored in it (even if right now that's basically
limited to the user list and ID).

Server was given more methods to help accessing contacts―
ContactById(BString) and AddContact(Contact*). This better allows
Conversations to add and fetch Contacts as necessary. Right now, all
users in chats are treated as Contacts, so in the future creating an
independent userlist for Server (fUserMap?) would be useful.

Server also now stores all Conversations (fChatMap) and has some
convenience methods like for Contacts: Conversations(),
ConversationById(BString), and AddConversation(Conversation*).

CayaRenderView has been changed to not store user nicks, and will use
the appropriate nick of any arbitrarily-numbered user.

Users also have a map of all Conversations they are a part of
(fChatMap).

The Remove* methods of KeyMap now return the removed item.
This commit is contained in:
Jaidyn Ann 2021-05-24 01:47:21 -05:00
parent 7822ec0449
commit 48d0b7bc96
20 changed files with 587 additions and 231 deletions

View File

@ -31,6 +31,7 @@
#include "CayaMessages.h" #include "CayaMessages.h"
#include "CayaProtocolMessages.h" #include "CayaProtocolMessages.h"
#include "CayaPreferences.h" #include "CayaPreferences.h"
#include "Conversation.h"
#include "Contact.h" #include "Contact.h"
#include "EditingFilter.h" #include "EditingFilter.h"
#include "CayaConstants.h" #include "CayaConstants.h"
@ -38,16 +39,16 @@
#include "NotifyMessage.h" #include "NotifyMessage.h"
ChatWindow::ChatWindow(Contact* cl) ChatWindow::ChatWindow(Conversation* cl)
: :
BWindow(BRect(200, 200, 500, 500), BWindow(BRect(200, 200, 500, 500),
cl->GetName().String(), B_TITLED_WINDOW, 0), cl->GetName().String(), B_TITLED_WINDOW, 0),
fContact(cl) fConversation(cl),
fContact(cl->Users().ValueAt(0))
{ {
fMessageCount = 0; fMessageCount = 0;
fReceiveView = new CayaRenderView("fReceiveView"); fReceiveView = new CayaRenderView("fReceiveView");
fReceiveView->SetOtherNick(cl->GetName());
BScrollView* scrollViewReceive = new BScrollView("scrollviewR", BScrollView* scrollViewReceive = new BScrollView("scrollviewR",
fReceiveView, B_WILL_DRAW, false, true); fReceiveView, B_WILL_DRAW, false, true);
@ -120,8 +121,8 @@ bool
ChatWindow::QuitRequested() ChatWindow::QuitRequested()
{ {
BMessage msg(CAYA_CLOSE_CHAT_WINDOW); BMessage msg(CAYA_CLOSE_CHAT_WINDOW);
msg.AddString("id", fContact->GetId()); msg.AddString("chat_id", fConversation->GetId());
fContact->Messenger().SendMessage(&msg); fConversation->Messenger().SendMessage(&msg);
return false; return false;
} }
@ -140,7 +141,6 @@ ChatWindow::UpdateAvatar()
void void
ChatWindow::UpdatePersonalMessage() ChatWindow::UpdatePersonalMessage()
{ {
if (fContact->GetNotifyPersonalStatus() != NULL) { if (fContact->GetNotifyPersonalStatus() != NULL) {
LockLooper(); LockLooper();
fPersonalMessage->SetText(fContact->GetNotifyPersonalStatus()); fPersonalMessage->SetText(fContact->GetNotifyPersonalStatus());
@ -163,9 +163,9 @@ ChatWindow::MessageReceived(BMessage* message)
BMessage msg(IM_MESSAGE); BMessage msg(IM_MESSAGE);
msg.AddInt32("im_what", IM_SEND_MESSAGE); msg.AddInt32("im_what", IM_SEND_MESSAGE);
msg.AddString("id", fContact->GetId()); msg.AddString("chat_id", fConversation->GetId());
msg.AddString("body", message); msg.AddString("body", message);
fContact->Messenger().SendMessage(&msg); fConversation->Messenger().SendMessage(&msg);
fSendView->SetText(""); fSendView->SetText("");
break; break;
@ -190,7 +190,11 @@ ChatWindow::ImMessage(BMessage* msg)
case IM_MESSAGE_RECEIVED: case IM_MESSAGE_RECEIVED:
{ {
BString message = msg->FindString("body"); BString message = msg->FindString("body");
fReceiveView->AppendOtherMessage(message.String()); BString id = msg->FindString("user_id");
User* sender = fConversation->UserById(id);
BString uname = sender->GetName();
fReceiveView->AppendOtherMessage(uname.String(), message.String());
// Message received, clear status anyway // Message received, clear status anyway
fStatus->SetText(""); fStatus->SetText("");
@ -202,9 +206,9 @@ ChatWindow::ImMessage(BMessage* msg)
// Mark unread window // Mark unread window
if (CayaPreferences::Item()->MarkUnreadWindow) { if (CayaPreferences::Item()->MarkUnreadWindow) {
BString title = "["; BString title = "[";
title<<fMessageCount; title << fMessageCount;
title<<"] "; title << "] ";
title<<fContact->GetName(); title << uname;
SetTitle(title); SetTitle(title);
} }
@ -220,14 +224,14 @@ ChatWindow::ImMessage(BMessage* msg)
} else { } else {
notify_message << " new messages from "; notify_message << " new messages from ";
}; };
notify_message << fContact->GetName().String(); notify_message << uname;
BNotification notification(B_INFORMATION_NOTIFICATION); BNotification notification(B_INFORMATION_NOTIFICATION);
notification.SetGroup(BString("Caya")); notification.SetGroup(BString("Caya"));
notification.SetTitle(BString("New message")); notification.SetTitle(BString("New message"));
notification.SetIcon(fAvatar->Bitmap()); notification.SetIcon(sender->AvatarBitmap());
notification.SetContent(notify_message); notification.SetContent(notify_message);
notification.SetMessageID(fContact->GetName()); notification.SetMessageID(uname);
notification.Send(); notification.Send();
break; break;
@ -248,6 +252,7 @@ ChatWindow::ImMessage(BMessage* msg)
} }
} }
void void
ChatWindow::WindowActivated(bool active) ChatWindow::WindowActivated(bool active)
{ {
@ -255,6 +260,7 @@ ChatWindow::WindowActivated(bool active)
fMessageCount=0; fMessageCount=0;
} }
void void
ChatWindow::ObserveString(int32 what, BString str) ChatWindow::ObserveString(int32 what, BString str)
{ {
@ -262,7 +268,6 @@ ChatWindow::ObserveString(int32 what, BString str)
case STR_CONTACT_NAME: case STR_CONTACT_NAME:
if (Lock()) { if (Lock()) {
SetTitle(str); SetTitle(str);
fReceiveView->SetOtherNick(str);
Unlock(); Unlock();
} }
break; break;

View File

@ -14,12 +14,14 @@
#include "CayaConstants.h" #include "CayaConstants.h"
class BitmapView; class BitmapView;
class Contact; class Conversation;
class CayaRenderView; class CayaRenderView;
class Contact;
class ChatWindow : public BWindow, public Observer { class ChatWindow : public BWindow, public Observer {
public: public:
ChatWindow(Contact* cl); ChatWindow(Conversation* cl);
virtual void ShowWindow(); virtual void ShowWindow();
@ -39,6 +41,7 @@ public:
void AvoidFocus(bool avoid); void AvoidFocus(bool avoid);
private: private:
BTextView* fSendView; BTextView* fSendView;
Conversation* fConversation;
Contact* fContact; Contact* fContact;
CayaRenderView* fReceiveView; CayaRenderView* fReceiveView;
BStringView* fStatus; BStringView* fStatus;
@ -49,3 +52,4 @@ private:
}; };
#endif // _CHAT_WINDOW_H #endif // _CHAT_WINDOW_H

View File

@ -9,83 +9,18 @@
*/ */
#include "Contact.h" #include "Contact.h"
#include "CayaPreferences.h"
#include "ChatWindow.h"
#include "RosterItem.h" #include "RosterItem.h"
#include "WindowsManager.h"
Contact::Contact(BString id, BMessenger msgn) Contact::Contact(BString id, BMessenger msgn)
: :
User::User(id, msgn), User::User(id, msgn)
fChatWindow(NULL),
fNewWindow(true)
{ {
fRosterItem = new RosterItem(id.String(), this); fRosterItem = new RosterItem(id.String(), this);
RegisterObserver(fRosterItem); RegisterObserver(fRosterItem);
} }
ChatWindow*
Contact::GetChatWindow()
{
if (fChatWindow == NULL)
_CreateChatWindow();
return fChatWindow;
}
void
Contact::DeleteWindow()
{
if (fChatWindow != NULL) {
if (fChatWindow->Lock()) {
UnregisterObserver(fChatWindow);
fChatWindow->Quit();
fChatWindow = NULL;
fNewWindow = true;
}
}
}
void
Contact::ShowWindow(bool typing, bool userAction)
{
if (fChatWindow == NULL)
_CreateChatWindow();
fChatWindow->AvoidFocus(true);
if (CayaPreferences::Item()->MoveToCurrentWorkspace)
fChatWindow->SetWorkspaces(B_CURRENT_WORKSPACE);
if (fNewWindow || userAction) {
fChatWindow->AvoidFocus(false);
fChatWindow->ShowWindow();
fNewWindow = false;
} else {
if (typing) {
if (CayaPreferences::Item()->RaiseUserIsTyping)
fChatWindow->ShowWindow();
} else {
if (CayaPreferences::Item()->RaiseOnMessageReceived
|| fChatWindow->IsHidden())
fChatWindow->ShowWindow();
}
}
fChatWindow->AvoidFocus(false);
}
void
Contact::HideWindow()
{
if ((fChatWindow != NULL) && !fChatWindow->IsHidden())
fChatWindow->Hide();
}
RosterItem* RosterItem*
Contact::GetRosterItem() const Contact::GetRosterItem() const
{ {
@ -97,15 +32,8 @@ void
Contact::SetNotifyAvatarBitmap(BBitmap* bitmap) Contact::SetNotifyAvatarBitmap(BBitmap* bitmap)
{ {
User::SetNotifyAvatarBitmap(bitmap); User::SetNotifyAvatarBitmap(bitmap);
if (fAvatarBitmap != NULL && fChatWindow != NULL) // if (fAvatarBitmap != NULL && fChatWindow != NULL)
fChatWindow->UpdateAvatar(); // fChatWindow->UpdateAvatar();
} }
void
Contact::_CreateChatWindow()
{
fChatWindow = new ChatWindow(this);
WindowsManager::Get()->RelocateWindow(fChatWindow);
RegisterObserver(fChatWindow);
}

View File

@ -15,7 +15,6 @@
class BBitmap; class BBitmap;
class ChatWindow;
class ProtocolLooper; class ProtocolLooper;
class RosterItem; class RosterItem;
@ -24,23 +23,12 @@ class Contact : public User {
public: public:
Contact(BString id, BMessenger msgn); Contact(BString id, BMessenger msgn);
ChatWindow* GetChatWindow();
void DeleteWindow();
void ShowWindow(bool typing = false, bool userAction = false);
void HideWindow();
RosterItem* GetRosterItem() const; RosterItem* GetRosterItem() const;
void SetNotifyAvatarBitmap(BBitmap* bitmap); void SetNotifyAvatarBitmap(BBitmap* bitmap);
private: private:
void _CreateChatWindow();
RosterItem* fRosterItem; RosterItem* fRosterItem;
ChatWindow* fChatWindow;
bool fNewWindow;
}; };
#endif // _CONTACT_LINKER_H_ #endif // _CONTACT_LINKER_H_

View File

@ -0,0 +1,240 @@
/*
* Copyright 2021, Jaidyn Levesque <jadedctrl@teknik.io>
* All rights reserved. Distributed under the terms of the MIT license.
*/
#include "Conversation.h"
#include "CayaPreferences.h"
#include "CayaProtocolMessages.h"
#include "ChatWindow.h"
#include "MainWindow.h"
#include "Server.h"
#include "TheApp.h"
#include "WindowsManager.h"
Conversation::Conversation(BString id, BMessenger msgn)
:
fID(id),
fName(id),
fMessenger(msgn),
fChatWindow(NULL),
fNewWindow(true),
fLooper(NULL)
{
}
BString
Conversation::GetId() const
{
return fID;
}
void
Conversation::ImMessage(BMessage* msg)
{
int32 im_what = msg->FindInt32("im_what");
switch(im_what)
{
case IM_MESSAGE_RECEIVED:
{
_EnsureUser(msg);
ChatWindow* win = GetChatWindow();
ShowWindow();
win->PostMessage(msg);
break;
}
default:
GetChatWindow()->PostMessage(msg);
}
}
void
Conversation::ObserveString(int32 what, BString str)
{
if (fChatWindow != NULL)
fChatWindow->ObserveString(what, str);
}
void
Conversation::ObservePointer(int32 what, void* ptr)
{
if (fChatWindow != NULL)
fChatWindow->ObservePointer(what, ptr);
}
void
Conversation::ObserveInteger(int32 what, int32 val)
{
if (fChatWindow != NULL)
fChatWindow->ObserveInteger(what, val);
}
ChatWindow*
Conversation::GetChatWindow()
{
if (fChatWindow == NULL)
_CreateChatWindow();
return fChatWindow;
}
void
Conversation::DeleteWindow()
{
if (fChatWindow != NULL) {
if (fChatWindow->Lock()) {
fChatWindow->Quit();
fChatWindow = NULL;
fNewWindow = true;
}
}
}
void
Conversation::ShowWindow(bool typing, bool userAction)
{
if (fChatWindow == NULL)
_CreateChatWindow();
fChatWindow->AvoidFocus(true);
if (CayaPreferences::Item()->MoveToCurrentWorkspace)
fChatWindow->SetWorkspaces(B_CURRENT_WORKSPACE);
if (fNewWindow || userAction) {
fChatWindow->AvoidFocus(false);
fChatWindow->ShowWindow();
fNewWindow = false;
} else {
if (typing) {
if (CayaPreferences::Item()->RaiseUserIsTyping)
fChatWindow->ShowWindow();
} else {
if (CayaPreferences::Item()->RaiseOnMessageReceived
|| fChatWindow->IsHidden())
fChatWindow->ShowWindow();
}
}
fChatWindow->AvoidFocus(false);
}
void
Conversation::HideWindow()
{
if ((fChatWindow != NULL) && !fChatWindow->IsHidden())
fChatWindow->Hide();
}
BMessenger
Conversation::Messenger() const
{
return fMessenger;
}
void
Conversation::SetMessenger(BMessenger messenger)
{
fMessenger = messenger;
}
ProtocolLooper*
Conversation::GetProtocolLooper() const
{
return fLooper;
}
void
Conversation::SetProtocolLooper(ProtocolLooper* looper)
{
fLooper = looper;
}
BString
Conversation::GetName() const
{
return fName;
}
UserMap
Conversation::Users()
{
return fUsers;
}
Contact*
Conversation::UserById(BString id)
{
bool found = false;
return fUsers.ValueFor(id, &found);
}
void
Conversation::AddUser(User* user)
{
BMessage msg;
msg.AddString("user_id", user->GetId());
_EnsureUser(&msg);
}
void
Conversation::_CreateChatWindow()
{
fChatWindow = new ChatWindow(this);
WindowsManager::Get()->RelocateWindow(fChatWindow);
}
Contact*
Conversation::_EnsureUser(BMessage* msg)
{
BString id = msg->FindString("user_id");
if (id.IsEmpty() == true) return NULL;
Contact* user = UserById(id);
Contact* serverUser = _GetServer()->ContactById(id);
if (user == NULL && serverUser != NULL) {
fUsers.AddItem(id, serverUser);
user = serverUser;
}
else if (user == NULL) {
user = new Contact(id, _GetServer()->Looper());
user->SetProtocolLooper(fLooper);
_GetServer()->AddContact(user);
fUsers.AddItem(id, user);
}
user->RegisterObserver(this);
return user;
}
Server*
Conversation::_GetServer()
{
return ((TheApp*)be_app)->GetMainWindow()->GetServer();
}

View File

@ -0,0 +1,74 @@
/*
* Copyright 2021, Jaidyn Levesque <jadedctrl@teknik.io>
* All rights reserved. Distributed under the terms of the MIT license.
*/
#ifndef CONVERSATION_H
#define CONVERSATION_H
#include <Messenger.h>
#include <libsupport/KeyMap.h>
#include "Notifier.h"
#include "User.h"
class ChatWindow;
class Contact;
class ProtocolLooper;
class Server;
typedef KeyMap<BString, Contact*> UserMap;
class Conversation : public Observer {
public:
Conversation(BString id, BMessenger msgn);
BString GetId() const;
// Handles required state changes from an IM message; forwards to ChatWindow
void ImMessage(BMessage* msg);
// Observer inherits; just forwards to ChatWindow
void ObserveString(int32 what, BString str);
void ObserveInteger(int32 what, int32 value);
void ObservePointer(int32 what, void* ptr);
ChatWindow* GetChatWindow();
void DeleteWindow();
void ShowWindow(bool typing = false, bool userAction = false);
void HideWindow();
BMessenger Messenger() const;
void SetMessenger(BMessenger messenger);
ProtocolLooper* GetProtocolLooper() const;
void SetProtocolLooper(ProtocolLooper* looper);
BString GetName() const;
UserMap Users();
Contact* UserById(BString id);
void AddUser(User* user);
private:
void _CreateChatWindow();
Contact* _EnsureUser(BMessage* msg);
Server* _GetServer();
BMessenger fMessenger;
ProtocolLooper* fLooper;
ChatWindow* fChatWindow;
bool fNewWindow;
BString fID;
BString fName;
UserMap fUsers;
};
#endif // CONVERSATION_H

View File

@ -161,7 +161,7 @@ MainWindow::MessageReceived(BMessage* message)
if (searchBox == NULL) if (searchBox == NULL)
return; return;
RosterMap map = fServer->RosterItems(); RosterMap map = fServer->Contacts();
for (uint32 i = 0; i < map.CountItems(); i++) { for (uint32 i = 0; i < map.CountItems(); i++) {
Contact* linker = map.ValueAt(i); Contact* linker = map.ValueAt(i);
RosterItem* item = linker->GetRosterItem(); RosterItem* item = linker->GetRosterItem();
@ -187,10 +187,29 @@ MainWindow::MessageReceived(BMessage* message)
} }
case CAYA_OPEN_CHAT_WINDOW: case CAYA_OPEN_CHAT_WINDOW:
{ {
// This is only used by RosterList, so try to open a one-on-one chat
// if there is one― otherwise, creawte one.
int index = message->FindInt32("index"); int index = message->FindInt32("index");
RosterItem* ritem = ItemAt(index); RosterItem* ritem = ItemAt(index);
User* user = ritem->GetContact();
if (ritem != NULL) if (ritem != NULL)
ritem->GetContact()->ShowWindow(false, true); User* user = ritem->GetContact();
ChatMap chats = user->Conversations();
Conversation* chat;
// TODO: Poor way of creating necessary chatroom
if (chats.CountItems() == 0) {
chat = new Conversation(user->GetId(), fServer->Looper());
chat->SetProtocolLooper(user->GetProtocolLooper());
chat->AddUser(user);
chat->ShowWindow(false, true);
fServer->AddConversation(chat);
}
else
while (chat = chats.RemoveItemAt(0))
if (chat->Users().CountItems() == 1)
chat->ShowWindow(false, true);
break; break;
} }
@ -283,7 +302,7 @@ MainWindow::ImMessage(BMessage* msg)
if (msg->FindInt32("status", &status) != B_OK) if (msg->FindInt32("status", &status) != B_OK)
return; return;
RosterItem* rosterItem = fServer->RosterItemForId(msg->FindString("id")); RosterItem* rosterItem = fServer->ContactById(msg->FindString("user_id"))->GetRosterItem();
if (rosterItem) { if (rosterItem) {
UpdateListItem(rosterItem); UpdateListItem(rosterItem);
@ -345,7 +364,7 @@ MainWindow::ImMessage(BMessage* msg)
case IM_EXTENDED_CONTACT_INFO: case IM_EXTENDED_CONTACT_INFO:
{ {
RosterItem* rosterItem RosterItem* rosterItem
= fServer->RosterItemForId(msg->FindString("id")); = fServer->ContactById(msg->FindString("user_id"))->GetRosterItem();
if (rosterItem) if (rosterItem)
UpdateListItem(rosterItem); UpdateListItem(rosterItem);
break; break;

View File

@ -18,6 +18,7 @@ class StatusView;
class RosterListView; class RosterListView;
class RosterItem; class RosterItem;
class MainWindow: public BWindow, public Observer { class MainWindow: public BWindow, public Observer {
public: public:
MainWindow(); MainWindow();

View File

@ -39,6 +39,7 @@ SRCS = \
application/CayaUtils.cpp \ application/CayaUtils.cpp \
application/ChatWindow.cpp \ application/ChatWindow.cpp \
application/Contact.cpp \ application/Contact.cpp \
application/Conversation.cpp \
application/EditingFilter.cpp \ application/EditingFilter.cpp \
application/ImageCache.cpp \ application/ImageCache.cpp \
application/Main.cpp \ application/Main.cpp \

View File

@ -2,19 +2,18 @@
* Copyright 2009-2011, Andrea Anzani. All rights reserved. * Copyright 2009-2011, Andrea Anzani. All rights reserved.
* Distributed under the terms of the MIT License. * Distributed under the terms of the MIT License.
*/ */
#ifndef Notifier_h_ #ifndef NOTIFIER_H
#define Notifier_h_ #define NOTIFIER_H
#include <String.h> #include <String.h>
#include <ObjectList.h> #include <ObjectList.h>
#include "Observer.h" #include "Observer.h"
class Notifier class Notifier
{ {
public: public:
void RegisterObserver(Observer*); void RegisterObserver(Observer*);
void UnregisterObserver(Observer*); void UnregisterObserver(Observer*);
@ -23,8 +22,9 @@ class Notifier
void NotifyPointer(int32 what, void* ptr); void NotifyPointer(int32 what, void* ptr);
private: private:
BObjectList<Observer> fObserverList; BObjectList<Observer> fObserverList;
}; };
#endif
#endif // NOTIFIER_H

View File

@ -42,13 +42,18 @@ Server::Server()
void void
Server::Quit() Server::Quit()
{ {
Contact* linker = NULL; Contact* contact = NULL;
Conversation* conversation = NULL;
while ((linker = fRosterMap.ValueAt(0))) { while (contact = fRosterMap.ValueAt(0)) {
linker->DeleteWindow(); contact->DeletePopUp();
linker->DeletePopUp();
fRosterMap.RemoveItemAt(0); fRosterMap.RemoveItemAt(0);
} }
while (conversation = fChatMap.ValueAt(0)) {
conversation->DeleteWindow();
fChatMap.RemoveItemAt(0);
}
} }
@ -121,27 +126,12 @@ Server::Filter(BMessage* message, BHandler **target)
filter_result result = B_DISPATCH_MESSAGE; filter_result result = B_DISPATCH_MESSAGE;
switch (message->what) { switch (message->what) {
case IM_MESSAGE_RECEIVED:
{
BString id = message->FindString("id");
if (id.Length() > 0) {
bool found = false;
Contact* item = fRosterMap.ValueFor(id, &found);
if (found) {
ChatWindow* win = item->GetChatWindow();
item->ShowWindow();
win->PostMessage(message);
}
}
result = B_SKIP_MESSAGE;
break;
}
case CAYA_CLOSE_CHAT_WINDOW: case CAYA_CLOSE_CHAT_WINDOW:
{ {
BString id = message->FindString("id"); BString id = message->FindString("chat_id");
if (id.Length() > 0) { if (id.Length() > 0) {
bool found = false; bool found = false;
Contact* item = fRosterMap.ValueFor(id, &found); Conversation* item = fChatMap.ValueFor(id, &found);
if (found) if (found)
item->HideWindow(); item->HideWindow();
@ -181,18 +171,46 @@ Server::Filter(BMessage* message, BHandler **target)
RosterMap RosterMap
Server::RosterItems() const Server::Contacts() const
{ {
return fRosterMap; return fRosterMap;
} }
RosterItem* Contact*
Server::RosterItemForId(BString id) Server::ContactById(BString id)
{ {
bool found = false; bool found = false;
Contact* item = fRosterMap.ValueFor(id, &found); return fRosterMap.ValueFor(id, &found);
return item ? item->GetRosterItem() : NULL; }
void
Server::AddContact(Contact* contact)
{
fRosterMap.AddItem(contact->GetId(), contact);
}
ChatMap
Server::Conversations() const
{
return fChatMap;
}
Conversation*
Server::ConversationById(BString id)
{
bool found = false;
return fChatMap.ValueFor(id, &found);
}
void
Server::AddConversation(Conversation* chat)
{
fChatMap.AddItem(chat->GetId(), chat);
} }
@ -207,7 +225,7 @@ Server::ImMessage(BMessage* msg)
{ {
int i = 0; int i = 0;
BString id; BString id;
while (msg->FindString("id", i++, &id) == B_OK) { while (msg->FindString("user_id", i++, &id) == B_OK) {
bool found = false; bool found = false;
Contact* item = fRosterMap.ValueFor(id, &found); Contact* item = fRosterMap.ValueFor(id, &found);
@ -223,7 +241,6 @@ Server::ImMessage(BMessage* msg)
} }
case IM_OWN_STATUS_SET: case IM_OWN_STATUS_SET:
{ {
//msg->PrintToStream();
int32 status; int32 status;
const char* protocol; const char* protocol;
if (msg->FindInt32("status", &status) != B_OK) if (msg->FindInt32("status", &status) != B_OK)
@ -243,104 +260,90 @@ Server::ImMessage(BMessage* msg)
if (msg->FindInt32("status", &status) != B_OK) if (msg->FindInt32("status", &status) != B_OK)
return B_SKIP_MESSAGE; return B_SKIP_MESSAGE;
Contact* linker = _EnsureContact(msg); Contact* contact = _EnsureContact(msg);
if (!linker) if (!contact)
break; break;
linker->SetNotifyStatus((CayaStatus)status); contact->SetNotifyStatus((CayaStatus)status);
BString statusMsg; BString statusMsg;
if (msg->FindString("message", &statusMsg) == B_OK) { if (msg->FindString("message", &statusMsg) == B_OK) {
linker->SetNotifyPersonalStatus(statusMsg); contact->SetNotifyPersonalStatus(statusMsg);
linker->GetChatWindow()->UpdatePersonalMessage(); // contact->GetChatWindow()->UpdatePersonalMessage();
} }
break; break;
} }
case IM_CONTACT_INFO: case IM_CONTACT_INFO:
{ {
Contact* linker = _EnsureContact(msg); Contact* contact = _EnsureContact(msg);
if (!linker) if (!contact)
break; break;
const char* name = NULL; const char* name = NULL;
if ((msg->FindString("name", &name) == B_OK) if ((msg->FindString("name", &name) == B_OK)
&& (strcmp(name, "") != 0)) && (strcmp(name, "") != 0))
linker->SetNotifyName(name); contact->SetNotifyName(name);
BString status; BString status;
if (msg->FindString("message", &status) == B_OK) { if (msg->FindString("message", &status) == B_OK) {
linker->SetNotifyPersonalStatus(status); contact->SetNotifyPersonalStatus(status);
linker->GetChatWindow()->UpdatePersonalMessage(); // contact->GetChatWindow()->UpdatePersonalMessage();
} }
break; break;
} }
case IM_EXTENDED_CONTACT_INFO: case IM_EXTENDED_CONTACT_INFO:
{ {
Contact* linker = _EnsureContact(msg); Contact* contact = _EnsureContact(msg);
if (!linker) if (!contact)
break; break;
if (linker->GetName().Length() > 0) if (contact->GetName().Length() > 0)
break; break;
const char* name = NULL; const char* name = NULL;
if ((msg->FindString("full name", &name) == B_OK) if ((msg->FindString("full name", &name) == B_OK)
&& (strcmp(name, "") != 0)) && (strcmp(name, "") != 0))
linker->SetNotifyName(name); contact->SetNotifyName(name);
break; break;
} }
case IM_AVATAR_SET: case IM_AVATAR_SET:
{ {
Contact* linker = _EnsureContact(msg); Contact* contact = _EnsureContact(msg);
if (!linker) if (!contact)
break; break;
entry_ref ref; entry_ref ref;
if (msg->FindRef("ref", &ref) == B_OK) { if (msg->FindRef("ref", &ref) == B_OK) {
BBitmap* bitmap = BTranslationUtils::GetBitmap(&ref); BBitmap* bitmap = BTranslationUtils::GetBitmap(&ref);
linker->SetNotifyAvatarBitmap(bitmap); contact->SetNotifyAvatarBitmap(bitmap);
} else } else
linker->SetNotifyAvatarBitmap(NULL); contact->SetNotifyAvatarBitmap(NULL);
break; break;
} }
case IM_SEND_MESSAGE: case IM_SEND_MESSAGE:
{ {
// Route this message through the appropriate ProtocolLooper // Route this message through the appropriate ProtocolLooper
Contact* linker = _EnsureContact(msg); Conversation* conversation = _EnsureConversation(msg);
if (linker->GetProtocolLooper()) if (conversation->GetProtocolLooper())
linker->GetProtocolLooper()->PostMessage(msg); conversation->GetProtocolLooper()->PostMessage(msg);
break; break;
} }
case IM_MESSAGE_RECEIVED: case IM_MESSAGE_RECEIVED:
{ {
BString id = msg->FindString("id"); Conversation* item = _EnsureConversation(msg);
if (id.Length() > 0) { item->ImMessage(msg);
bool found = false;
Contact* item = fRosterMap.ValueFor(id, &found);
if (found) {
ChatWindow* win = item->GetChatWindow();
item->ShowWindow();
win->PostMessage(msg);
}
}
result = B_SKIP_MESSAGE; result = B_SKIP_MESSAGE;
break; break;
} }
case IM_CONTACT_STARTED_TYPING: case IM_CONTACT_STARTED_TYPING:
case IM_CONTACT_STOPPED_TYPING: case IM_CONTACT_STOPPED_TYPING:
{ {
BString id = msg->FindString("id"); BString id = msg->FindString("chat_id");
if (id.Length() > 0) { Conversation* item = _EnsureConversation(msg);
bool found = false; item->ImMessage(msg);
Contact* item = fRosterMap.ValueFor(id, &found);
if (found) {
ChatWindow* win = item->GetChatWindow();
item->ShowWindow(true);
win->PostMessage(msg);
}
}
result = B_SKIP_MESSAGE; result = B_SKIP_MESSAGE;
break; break;
} }
@ -444,26 +447,59 @@ Server::_LooperFromMessage(BMessage* message)
Contact* Contact*
Server::_EnsureContact(BMessage* message) Server::_GetContact(BMessage* message)
{ {
if (!message) if (!message)
return NULL; return NULL;
BString id = message->FindString("id"); BString id = message->FindString("user_id");
Contact* item = NULL; Contact* item = NULL;
if (id.Length() > 0) { if (id.IsEmpty() == false) {
bool found = false; bool found = false;
item = fRosterMap.ValueFor(id, &found); item = fRosterMap.ValueFor(id, &found);
if (!found) {
item = new Contact(id.String(), Looper());
item->SetProtocolLooper(_LooperFromMessage(message));
fRosterMap.AddItem(id, item);
}
} }
return item; return item;
} }
Contact*
Server::_EnsureContact(BMessage* message)
{
Contact* contact = _GetContact(message);
BString id = message->FindString("user_id");
if (contact == NULL && id.IsEmpty() == false) {
contact = new Contact(id, Looper());
contact->SetProtocolLooper(_LooperFromMessage(message));
fRosterMap.AddItem(id, contact);
}
return contact;
}
Conversation*
Server::_EnsureConversation(BMessage* message)
{
if (!message)
return NULL;
BString chat_id = message->FindString("chat_id");
Conversation* item = NULL;
if (chat_id.IsEmpty() == false) {
bool found = false;
item = fChatMap.ValueFor(chat_id, &found);
if (!found) {
item = new Conversation(chat_id, Looper());
item->SetProtocolLooper(_LooperFromMessage(message));
fChatMap.AddItem(chat_id, item);
}
}
return item;
}

View File

@ -13,12 +13,14 @@
#include "CayaConstants.h" #include "CayaConstants.h"
#include "Contact.h" #include "Contact.h"
#include "Conversation.h"
class CayaProtocol; class CayaProtocol;
class RosterItem; class RosterItem;
class ProtocolLooper; class ProtocolLooper;
typedef KeyMap<BString, Contact*> RosterMap; typedef KeyMap<BString, Contact*> RosterMap;
typedef KeyMap<BString, Conversation*> ChatMap;
typedef KeyMap<bigtime_t, ProtocolLooper*> ProtocolLoopers; typedef KeyMap<bigtime_t, ProtocolLooper*> ProtocolLoopers;
class Server: public BMessageFilter { class Server: public BMessageFilter {
@ -39,18 +41,26 @@ public:
void SendProtocolMessage(BMessage* msg); void SendProtocolMessage(BMessage* msg);
void SendAllProtocolMessage(BMessage* msg); void SendAllProtocolMessage(BMessage* msg);
RosterMap RosterItems() const; RosterMap Contacts() const;
RosterItem* RosterItemForId(BString id); Contact* ContactById(BString id);
void AddContact(Contact* contact);
ChatMap Conversations() const;
Conversation* ConversationById(BString id);
void AddConversation(Conversation* chat);
// TODO: there should be a contact for each account. // TODO: there should be a contact for each account.
Contact* GetOwnContact(); Contact* GetOwnContact();
private: private:
ProtocolLooper* _LooperFromMessage(BMessage* message); ProtocolLooper* _LooperFromMessage(BMessage* message);
Contact* _GetContact(BMessage* message);
Contact* _EnsureContact(BMessage* message); Contact* _EnsureContact(BMessage* message);
Conversation* _EnsureConversation(BMessage* message);
void _ReplicantStatusNotify(CayaStatus status); void _ReplicantStatusNotify(CayaStatus status);
RosterMap fRosterMap; RosterMap fRosterMap;
ChatMap fChatMap;
ProtocolLoopers fLoopers; ProtocolLoopers fLoopers;
Contact* fMySelf; Contact* fMySelf;
}; };

View File

@ -14,6 +14,7 @@
#include "CayaProtocolAddOn.h" #include "CayaProtocolAddOn.h"
#include "CayaResources.h" #include "CayaResources.h"
#include "CayaUtils.h" #include "CayaUtils.h"
#include "Conversation.h"
#include "NotifyMessage.h" #include "NotifyMessage.h"
#include "ProtocolLooper.h" #include "ProtocolLooper.h"
#include "ProtocolManager.h" #include "ProtocolManager.h"
@ -32,6 +33,22 @@ User::User(BString id, BMessenger msgn)
} }
void
User::RegisterObserver(Conversation* chat)
{
Notifier::RegisterObserver(chat);
fConversations.AddItem(chat->GetId(), chat);
}
void
User::UnregisterObserver(Conversation* chat)
{
Notifier::UnregisterObserver(chat);
fConversations.RemoveItemFor(chat->GetId());
}
void void
User::ShowPopUp(BPoint where) User::ShowPopUp(BPoint where)
{ {
@ -190,3 +207,10 @@ User::SetNotifyPersonalStatus(BString personalStatus)
} }
ChatMap
User::Conversations()
{
return fConversations;
}

View File

@ -3,12 +3,15 @@
* Copyright 2012, Dario Casalinuovo. All rights reserved. * Copyright 2012, Dario Casalinuovo. All rights reserved.
* Distributed under the terms of the MIT License. * Distributed under the terms of the MIT License.
*/ */
#ifndef _USER_H_ #ifndef USER_H
#define _USER_H_ #define USER_H
#include <String.h> #include <String.h>
#include <Message.h> #include <Message.h>
#include <Messenger.h> #include <Messenger.h>
#include <ObjectList.h>
#include <libsupport/KeyMap.h>
#include "Notifier.h" #include "Notifier.h"
#include "CayaConstants.h" #include "CayaConstants.h"
@ -16,14 +19,24 @@
class BBitmap; class BBitmap;
class ChatWindow; class ChatWindow;
class Conversation;
class UserPopUp; class UserPopUp;
class ProtocolLooper; class ProtocolLooper;
class RosterItem; class RosterItem;
typedef KeyMap<BString, Conversation*> ChatMap;
class User : public Notifier { class User : public Notifier {
public: public:
User(BString id, BMessenger msgn); User(BString id, BMessenger msgn);
void RegisterObserver(Conversation* chat);
void RegisterObserver(Observer* obs) { Notifier::RegisterObserver(obs); }
void UnregisterObserver(Conversation* chat);
void UnregisterObserver(Observer* obs) { Notifier::UnregisterObserver(obs); }
void ShowPopUp(BPoint where); void ShowPopUp(BPoint where);
void DeletePopUp(); void DeletePopUp();
void HidePopUp(); void HidePopUp();
@ -47,6 +60,8 @@ public:
void SetNotifyStatus(CayaStatus status); void SetNotifyStatus(CayaStatus status);
void SetNotifyPersonalStatus(BString personalStatus); void SetNotifyPersonalStatus(BString personalStatus);
ChatMap Conversations();
protected: protected:
BMessenger fMessenger; BMessenger fMessenger;
ProtocolLooper* fLooper; ProtocolLooper* fLooper;
@ -58,6 +73,9 @@ protected:
BBitmap* fAvatarBitmap; BBitmap* fAvatarBitmap;
CayaStatus fStatus; CayaStatus fStatus;
UserPopUp* fPopUp; UserPopUp* fPopUp;
ChatMap fConversations;
}; };
#endif // _USER_H_
#endif // USER_H

View File

@ -26,20 +26,22 @@ CayaRenderView::CayaRenderView(const char *name, const char* smileyConfig)
ScrollToBottom(); ScrollToBottom();
} }
void void
CayaRenderView::AppendOtherMessage(const char* message) CayaRenderView::AppendOtherMessage(const char* otherNick, const char* message)
{ {
Append(fOtherNick.String(), COL_OTHERNICK, COL_OTHERNICK, R_TEXT); Append(otherNick, COL_OTHERNICK, COL_OTHERNICK, R_TEXT);
Append(": ", COL_OTHERNICK, COL_OTHERNICK, R_TEXT); Append(": ", COL_OTHERNICK, COL_OTHERNICK, R_TEXT);
AddEmoticText(message, COL_TEXT, R_TEXT, COL_TEXT,R_EMOTICON); AddEmoticText(message, COL_TEXT, R_TEXT, COL_TEXT,R_EMOTICON);
Append("\n", COL_TEXT, COL_TEXT, R_TEXT); Append("\n", COL_TEXT, COL_TEXT, R_TEXT);
ScrollToSelection(); ScrollToSelection();
} }
void void
CayaRenderView::AppendOwnMessage(const char* message) CayaRenderView::AppendOwnMessage(const char* message)
{ {
Append("You say: ", COL_OWNNICK, COL_OWNNICK, R_TEXT); Append("You: ", COL_OWNNICK, COL_OWNNICK, R_TEXT);
AddEmoticText(message, COL_TEXT, R_TEXT,COL_TEXT,R_EMOTICON); AddEmoticText(message, COL_TEXT, R_TEXT,COL_TEXT,R_EMOTICON);
Append("\n", COL_TEXT, COL_TEXT, R_TEXT); Append("\n", COL_TEXT, COL_TEXT, R_TEXT);
ScrollToSelection(); ScrollToSelection();
@ -55,6 +57,7 @@ CayaRenderView::AddEmoticText(const char * txt, int16 cols , int16 font , int16
Emoticor::Get()->AddText(this, txt, cols, font, cols2, font2); Emoticor::Get()->AddText(this, txt, cols, font, cols2, font2);
} }
void void
CayaRenderView::PrepareTheme(Theme *fTheme) CayaRenderView::PrepareTheme(Theme *fTheme)
{ {
@ -97,5 +100,6 @@ CayaRenderView::PrepareTheme(Theme *fTheme)
fTheme->SetTextMargin(5.0); fTheme->SetTextMargin(5.0);
fTheme->WriteUnlock(); fTheme->WriteUnlock();
} }

View File

@ -37,19 +37,14 @@ class CayaRenderView : public RunView
public: public:
CayaRenderView(const char* name, const char* smileyConfig = NULL); CayaRenderView(const char* name, const char* smileyConfig = NULL);
void AppendOtherMessage(const char* message); void AppendOtherMessage(const char* otherNick, const char* message);
void AppendOwnMessage(const char* message); void AppendOwnMessage(const char* message);
void AddEmoticText(const char * txt, int16 cols , int16 font , int16 cols2 , int16 font2); void AddEmoticText(const char * txt, int16 cols , int16 font , int16 cols2 , int16 font2);
void SetOwnNick(BString nick) { fOwnNick = nick; }
void SetOtherNick(BString nick) { fOtherNick = nick; }
protected: protected:
void PrepareTheme(Theme* theme); void PrepareTheme(Theme* theme);
private: private:
BString fOwnNick;
BString fOtherNick;
Theme* fTheme; Theme* fTheme;
SmileTextRender str; SmileTextRender str;

View File

@ -116,8 +116,8 @@ RosterListView::MessageReceived(BMessage* msg)
{ {
if (ritem == NULL) if (ritem == NULL)
return; return;
Contact* link = ritem->GetContact(); // Contact* link = ritem->GetContact();
link->ShowWindow(false, true); // link->ShowWindow(false, true);
break; break;
} }

View File

@ -18,8 +18,8 @@ public:
TYPE ValueFor(KEY, bool* found = NULL) const; TYPE ValueFor(KEY, bool* found = NULL) const;
void RemoveItemAt(int32 position); TYPE RemoveItemAt(int32 position);
void RemoveItemFor(KEY); TYPE RemoveItemFor(KEY);
KEY KeyAt(uint32 position) const; KEY KeyAt(uint32 position) const;
TYPE ValueAt(uint32 position) const; TYPE ValueAt(uint32 position) const;
@ -69,20 +69,24 @@ KeyMap<KEY, TYPE>::ValueFor(KEY k, bool* found) const
template<class KEY, class TYPE> template<class KEY, class TYPE>
inline void inline TYPE
KeyMap<KEY, TYPE>::RemoveItemAt(int32 position) KeyMap<KEY, TYPE>::RemoveItemAt(int32 position)
{ {
TYPE value = ValueAt(position);
fIter i = fMap.begin(); fIter i = fMap.begin();
std::advance(i, position); std::advance(i, position);
fMap.erase(i->first); fMap.erase(i->first);
return value;
} }
template<class KEY, class TYPE> template<class KEY, class TYPE>
inline void inline TYPE
KeyMap<KEY, TYPE>::RemoveItemFor(KEY k) KeyMap<KEY, TYPE>::RemoveItemFor(KEY k)
{ {
TYPE value = ValueFor(k);
fMap.erase(k); fMap.erase(k);
return value;
} }

View File

@ -103,7 +103,7 @@ JabberHandler::Process(BMessage* msg)
break; break;
} }
case IM_SEND_MESSAGE: { case IM_SEND_MESSAGE: {
const char* id = msg->FindString("id"); const char* id = msg->FindString("chat_id");
const char* subject = msg->FindString("subject"); const char* subject = msg->FindString("subject");
const char* body = msg->FindString("body"); const char* body = msg->FindString("body");
@ -527,7 +527,8 @@ JabberHandler::_MessageSent(const char* id, const char* subject,
{ {
BMessage msg(IM_MESSAGE); BMessage msg(IM_MESSAGE);
msg.AddInt32("im_what", IM_MESSAGE_SENT); msg.AddInt32("im_what", IM_MESSAGE_SENT);
msg.AddString("id", id); msg.AddString("user_id", id);
msg.AddString("chat_id", id);
msg.AddString("subject", subject); msg.AddString("subject", subject);
msg.AddString("body", body); msg.AddString("body", body);
_SendMessage(&msg); _SendMessage(&msg);
@ -662,7 +663,7 @@ JabberHandler::_AvatarChanged(const char* id, const char* filename)
msg.AddInt32("im_what", IM_OWN_AVATAR_SET); msg.AddInt32("im_what", IM_OWN_AVATAR_SET);
else { else {
msg.AddInt32("im_what", IM_AVATAR_SET); msg.AddInt32("im_what", IM_AVATAR_SET);
msg.AddString("id", id); msg.AddString("user_id", id);
} }
msg.AddRef("ref", &ref); msg.AddRef("ref", &ref);
_SendMessage(&msg); _SendMessage(&msg);
@ -803,12 +804,12 @@ JabberHandler::handleRoster(const gloox::Roster& roster)
int32 subscription = (*it).second->subscription(); int32 subscription = (*it).second->subscription();
// Add jid to the server based contact list message // Add jid to the server based contact list message
contactListMsg.AddString("id", jid); contactListMsg.AddString("user_id", jid);
// Contact information message // Contact information message
BMessage infoMsg(IM_MESSAGE); BMessage infoMsg(IM_MESSAGE);
infoMsg.AddInt32("im_what", IM_CONTACT_INFO); infoMsg.AddInt32("im_what", IM_CONTACT_INFO);
infoMsg.AddString("id", jid); infoMsg.AddString("user_id", jid);
infoMsg.AddString("name", name); infoMsg.AddString("name", name);
infoMsg.AddInt32("subscription", subscription); infoMsg.AddInt32("subscription", subscription);
infoMsg.AddInt32("status", CAYA_OFFLINE); infoMsg.AddInt32("status", CAYA_OFFLINE);
@ -836,7 +837,7 @@ JabberHandler::handleRoster(const gloox::Roster& roster)
std::list<BMessage>::iterator msgsIt; std::list<BMessage>::iterator msgsIt;
for (msgsIt = msgs.begin(); msgsIt != msgs.end(); ++msgsIt) { for (msgsIt = msgs.begin(); msgsIt != msgs.end(); ++msgsIt) {
BMessage msg = (*msgsIt); BMessage msg = (*msgsIt);
const char* jid = msg.FindString("id"); const char* jid = msg.FindString("user_id");
_SendMessage(&msg); _SendMessage(&msg);
fVCardManager->fetchVCard(gloox::JID(jid), this); fVCardManager->fetchVCard(gloox::JID(jid), this);
} }
@ -879,7 +880,8 @@ JabberHandler::handleMessage(const gloox::Message& m, gloox::MessageSession*)
// Notify that a chat message was received // Notify that a chat message was received
BMessage msg(IM_MESSAGE); BMessage msg(IM_MESSAGE);
msg.AddString("id", m.from().bare().c_str()); msg.AddString("user_id", m.from().bare().c_str());
msg.AddString("chat_id", m.from().bare().c_str());
msg.AddInt32("im_what", IM_MESSAGE_RECEIVED); msg.AddInt32("im_what", IM_MESSAGE_RECEIVED);
if (m.subject() != "") if (m.subject() != "")
msg.AddString("subject", m.subject().c_str()); msg.AddString("subject", m.subject().c_str());
@ -903,7 +905,8 @@ printf("------ %d\n", state);
return; return;
BMessage msg(IM_MESSAGE); BMessage msg(IM_MESSAGE);
msg.AddString("id", from.bare().c_str()); msg.AddString("user_id", from.bare().c_str());
msg.AddString("chat_id", from.bare().c_str());
switch (state) { switch (state) {
case gloox::ChatStateComposing: case gloox::ChatStateComposing:
@ -961,7 +964,7 @@ JabberHandler::handleRosterPresence(const gloox::RosterItem& item,
{ {
BMessage msg(IM_MESSAGE); BMessage msg(IM_MESSAGE);
msg.AddInt32("im_what", IM_STATUS_SET); msg.AddInt32("im_what", IM_STATUS_SET);
msg.AddString("id", item.jidJID().full().c_str()); msg.AddString("user_id", item.jidJID().full().c_str());
msg.AddInt32("status", _GlooxStatusToCaya(type)); msg.AddInt32("status", _GlooxStatusToCaya(type));
msg.AddString("resource", resource.c_str()); msg.AddString("resource", resource.c_str());
msg.AddString("message", presenceMsg.c_str()); msg.AddString("message", presenceMsg.c_str());
@ -977,7 +980,7 @@ JabberHandler::handleSelfPresence(const gloox::RosterItem& item, const std::stri
BMessage msg(IM_MESSAGE); BMessage msg(IM_MESSAGE);
msg.AddInt32("im_what", IM_OWN_CONTACT_INFO); msg.AddInt32("im_what", IM_OWN_CONTACT_INFO);
msg.AddString("protocol", Signature()); msg.AddString("protocol", Signature());
msg.AddString("id", item.jidJID().full().c_str()); msg.AddString("user_id", item.jidJID().full().c_str());
msg.AddString("name", item.name().c_str()); msg.AddString("name", item.name().c_str());
msg.AddInt32("subscription", item.subscription()); msg.AddInt32("subscription", item.subscription());
msg.AddInt32("status", _GlooxStatusToCaya(type)); msg.AddInt32("status", _GlooxStatusToCaya(type));
@ -1047,7 +1050,7 @@ JabberHandler::handleVCard(const gloox::JID& jid, const gloox::VCard* card)
BMessage msg(IM_MESSAGE); BMessage msg(IM_MESSAGE);
msg.AddInt32("im_what", IM_EXTENDED_CONTACT_INFO); msg.AddInt32("im_what", IM_EXTENDED_CONTACT_INFO);
msg.AddString("id", jid.bare().c_str()); msg.AddString("user_id", jid.bare().c_str());
msg.AddString("nick", card->nickname().c_str()); msg.AddString("nick", card->nickname().c_str());
msg.AddString("family name", name.family.c_str()); msg.AddString("family name", name.family.c_str());
msg.AddString("given name", name.given.c_str()); msg.AddString("given name", name.given.c_str());

View File

@ -32,9 +32,11 @@ APP_MIME_SIG =
# same name (source.c or source.cpp) are included from different directories. # same name (source.c or source.cpp) are included from different directories.
# Also note that spaces in folder names do not work well with this Makefile. # Also note that spaces in folder names do not work well with this Makefile.
SRCS = \ SRCS = \
protocols/xmpp/FacebookProtocol.cpp \
protocols/xmpp/GoogleTalkProtocol.cpp \
protocols/xmpp/JabberHandler.cpp \
protocols/xmpp/JabberMain.cpp \ protocols/xmpp/JabberMain.cpp \
protocols/xmpp/JabberProtocol.cpp \ protocols/xmpp/JabberProtocol.cpp
protocols/xmpp/JabberHandler.cpp
# Specify the resource definition files to use. Full or relative paths can be # Specify the resource definition files to use. Full or relative paths can be