summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Swift/Controllers/Chat/ChatsManager.cpp5
-rw-r--r--Swift/Controllers/Chat/ChatsManager.h4
-rw-r--r--Swift/Controllers/Chat/MUCController.cpp35
-rw-r--r--Swift/Controllers/Chat/MUCController.h8
-rw-r--r--Swift/Controllers/MainController.cpp4
-rw-r--r--Swiften/MUC/MUC.cpp37
-rw-r--r--Swiften/MUC/MUC.h11
7 files changed, 94 insertions, 10 deletions
diff --git a/Swift/Controllers/Chat/ChatsManager.cpp b/Swift/Controllers/Chat/ChatsManager.cpp
index 69184ad..1ee501a 100644
--- a/Swift/Controllers/Chat/ChatsManager.cpp
+++ b/Swift/Controllers/Chat/ChatsManager.cpp
@@ -28,7 +28,8 @@ namespace Swift {
typedef std::pair<JID, ChatController*> JIDChatControllerPair;
typedef std::pair<JID, MUCController*> JIDMUCControllerPair;
-ChatsManager::ChatsManager(JID jid, StanzaChannel* stanzaChannel, IQRouter* iqRouter, EventController* eventController, ChatWindowFactory* chatWindowFactory, NickResolver* nickResolver, PresenceOracle* presenceOracle, boost::shared_ptr<DiscoInfo> serverDiscoInfo, PresenceSender* presenceSender, UIEventStream* uiEventStream, ChatListWindowFactory* chatListWindowFactory, bool useDelayForLatency) : jid_(jid), useDelayForLatency_(useDelayForLatency) {
+ChatsManager::ChatsManager(JID jid, StanzaChannel* stanzaChannel, IQRouter* iqRouter, EventController* eventController, ChatWindowFactory* chatWindowFactory, NickResolver* nickResolver, PresenceOracle* presenceOracle, boost::shared_ptr<DiscoInfo> serverDiscoInfo, PresenceSender* presenceSender, UIEventStream* uiEventStream, ChatListWindowFactory* chatListWindowFactory, bool useDelayForLatency, TimerFactory* timerFactory) : jid_(jid), useDelayForLatency_(useDelayForLatency) {
+ timerFactory_ = timerFactory;
eventController_ = eventController;
stanzaChannel_ = stanzaChannel;
iqRouter_ = iqRouter;
@@ -220,7 +221,7 @@ void ChatsManager::handleJoinMUCRequest(const JID &muc, const boost::optional<St
//FIXME: What's correct behaviour here?
} else {
String nick = nickMaybe ? nickMaybe.get() : "Swift user";
- MUCController* controller = new MUCController(jid_, muc, nick, stanzaChannel_, presenceSender_, iqRouter_, chatWindowFactory_, presenceOracle_, avatarManager_, uiEventStream_, false);
+ MUCController* controller = new MUCController(jid_, muc, nick, stanzaChannel_, presenceSender_, iqRouter_, chatWindowFactory_, presenceOracle_, avatarManager_, uiEventStream_, false, timerFactory_);
mucControllers_[muc] = controller;
controller->setAvailableServerFeatures(serverDiscoInfo_);
controller->onUserLeft.connect(boost::bind(&ChatsManager::handleUserLeftMUC, this, controller));
diff --git a/Swift/Controllers/Chat/ChatsManager.h b/Swift/Controllers/Chat/ChatsManager.h
index 1f0f203..9957891 100644
--- a/Swift/Controllers/Chat/ChatsManager.h
+++ b/Swift/Controllers/Chat/ChatsManager.h
@@ -33,10 +33,11 @@ namespace Swift {
class MUCBookmarkManager;
class ChatListWindow;
class ChatListWindowFactory;
+ class TimerFactory;
class ChatsManager : public MUCRegistry {
public:
- ChatsManager(JID jid, StanzaChannel* stanzaChannel, IQRouter* iqRouter, EventController* eventController, ChatWindowFactory* chatWindowFactory, NickResolver* nickResolver, PresenceOracle* presenceOracle, boost::shared_ptr<DiscoInfo> serverDiscoInfo, PresenceSender* presenceSender, UIEventStream* uiEventStream, ChatListWindowFactory* chatListWindowFactory, bool useDelayForLatency);
+ ChatsManager(JID jid, StanzaChannel* stanzaChannel, IQRouter* iqRouter, EventController* eventController, ChatWindowFactory* chatWindowFactory, NickResolver* nickResolver, PresenceOracle* presenceOracle, boost::shared_ptr<DiscoInfo> serverDiscoInfo, PresenceSender* presenceSender, UIEventStream* uiEventStream, ChatListWindowFactory* chatListWindowFactory, bool useDelayForLatency, TimerFactory* timerFactory);
~ChatsManager();
void setAvatarManager(AvatarManager* avatarManager);
void setEnabled(bool enabled);
@@ -74,5 +75,6 @@ namespace Swift {
ChatListWindow* chatListWindow_;
boost::bsignals::scoped_connection uiEventConnection_;
bool useDelayForLatency_;
+ TimerFactory* timerFactory_;
};
}
diff --git a/Swift/Controllers/Chat/MUCController.cpp b/Swift/Controllers/Chat/MUCController.cpp
index 7e9a9ea..a8a6747 100644
--- a/Swift/Controllers/Chat/MUCController.cpp
+++ b/Swift/Controllers/Chat/MUCController.cpp
@@ -8,6 +8,8 @@
#include <boost/bind.hpp>
+#include "Swiften/Network/Timer.h"
+#include "Swiften/Network/TimerFactory.h"
#include "Swiften/Base/foreach.h"
#include "Swift/Controllers/UIInterfaces/ChatWindow.h"
#include "Swift/Controllers/UIInterfaces/ChatWindowFactory.h"
@@ -20,6 +22,8 @@
#include "Swiften/Roster/SetAvatar.h"
#include "Swiften/Roster/SetPresence.h"
+#define MUC_JOIN_WARNING_TIMEOUT_MILLISECONDS 60000
+
namespace Swift {
/**
@@ -36,20 +40,29 @@ MUCController::MUCController (
PresenceOracle* presenceOracle,
AvatarManager* avatarManager,
UIEventStream* uiEventStream,
- bool useDelayForLatency) :
+ bool useDelayForLatency,
+ TimerFactory* timerFactory) :
ChatControllerBase(self, stanzaChannel, iqRouter, chatWindowFactory, muc, presenceOracle, avatarManager, useDelayForLatency, uiEventStream),
muc_(new MUC(stanzaChannel, presenceSender, muc)),
- nick_(nick) {
+ nick_(nick) {
+ loginCheckTimer_ = boost::shared_ptr<Timer>(timerFactory->createTimer(MUC_JOIN_WARNING_TIMEOUT_MILLISECONDS));
parting_ = false;
events_ = uiEventStream;
+
roster_ = new Roster();
chatWindow_->setRosterModel(roster_);
chatWindow_->onClosed.connect(boost::bind(&MUCController::handleWindowClosed, this));
- muc_->joinAs(nick);
+ muc_->onJoinComplete.connect(boost::bind(&MUCController::handleJoinComplete, this, _1));
muc_->onOccupantJoined.connect(boost::bind(&MUCController::handleOccupantJoined, this, _1));
muc_->onOccupantPresenceChange.connect(boost::bind(&MUCController::handleOccupantPresenceChange, this, _1));
muc_->onOccupantLeft.connect(boost::bind(&MUCController::handleOccupantLeft, this, _1, _2, _3));
+ loginCheckTimer_->onTick.connect(boost::bind(&MUCController::handleJoinTimeoutTick, this));
+ loginCheckTimer_->start();
+
+ muc_->joinAs(nick);
chatWindow_->convertToMUC();
+ chatWindow_->addSystemMessage("Trying to join room " + toJID_.toString());
+ joined_ = false;
if (avatarManager_ != NULL) {
avatarChangedConnection_ = (avatarManager_->onAvatarChanged.connect(boost::bind(&MUCController::handleAvatarChanged, this, _1, _2)));
}
@@ -59,6 +72,22 @@ MUCController::~MUCController() {
delete muc_;
chatWindow_->setRosterModel(NULL);
delete roster_;
+ loginCheckTimer_->stop();
+}
+
+void MUCController::handleJoinTimeoutTick() {
+ loginCheckTimer_->stop();
+ chatWindow_->addSystemMessage("Room " + toJID_.toString() + " is not responding. This operation may never complete");
+}
+
+void MUCController::handleJoinComplete(MUC::JoinResult result) {
+ loginCheckTimer_->stop();
+ if (result == MUC::JoinFailed) {
+ chatWindow_->addErrorMessage("Unable to join this room");
+ }
+ joined_ = true;
+ String joinMessage = "You have joined room " + toJID_.toString() + " as " + nick_;
+ chatWindow_->addSystemMessage(joinMessage);
}
void MUCController::handleAvatarChanged(const JID& jid, const String&) {
diff --git a/Swift/Controllers/Chat/MUCController.h b/Swift/Controllers/Chat/MUCController.h
index 8e6e01b..9e79835 100644
--- a/Swift/Controllers/Chat/MUCController.h
+++ b/Swift/Controllers/Chat/MUCController.h
@@ -12,6 +12,7 @@
#include <boost/signals/connection.hpp>
#include "Swiften/Base/String.h"
+#include "Swiften/Network/Timer.h"
#include "Swift/Controllers/Chat/ChatControllerBase.h"
#include "Swiften/Elements/Message.h"
#include "Swiften/Elements/DiscoInfo.h"
@@ -27,10 +28,11 @@ namespace Swift {
class Roster;
class AvatarManager;
class UIEventStream;
+ class TimerFactory;
class MUCController : public ChatControllerBase {
public:
- MUCController(const JID& self, const JID &muc, const String &nick, StanzaChannel* stanzaChannel, PresenceSender* presenceSender, IQRouter* iqRouter, ChatWindowFactory* chatWindowFactory, PresenceOracle* presenceOracle, AvatarManager* avatarManager, UIEventStream* events, bool useDelayForLatency);
+ MUCController(const JID& self, const JID &muc, const String &nick, StanzaChannel* stanzaChannel, PresenceSender* presenceSender, IQRouter* iqRouter, ChatWindowFactory* chatWindowFactory, PresenceOracle* presenceOracle, AvatarManager* avatarManager, UIEventStream* events, bool useDelayForLatency, TimerFactory* timerFactory);
~MUCController();
boost::signal<void ()> onUserLeft;
@@ -45,6 +47,8 @@ namespace Swift {
void handleOccupantJoined(const MUCOccupant& occupant);
void handleOccupantLeft(const MUCOccupant& occupant, MUC::LeavingType type, const String& reason);
void handleOccupantPresenceChange(boost::shared_ptr<Presence> presence);
+ void handleJoinComplete(MUC::JoinResult result);
+ void handleJoinTimeoutTick();
private:
MUC* muc_;
@@ -52,7 +56,9 @@ namespace Swift {
String nick_;
Roster* roster_;
bool parting_;
+ bool joined_;
boost::bsignals::scoped_connection avatarChangedConnection_;
+ boost::shared_ptr<Timer> loginCheckTimer_;
};
}
#endif
diff --git a/Swift/Controllers/MainController.cpp b/Swift/Controllers/MainController.cpp
index 13426eb..6c9c5dd 100644
--- a/Swift/Controllers/MainController.cpp
+++ b/Swift/Controllers/MainController.cpp
@@ -13,6 +13,8 @@
#include "Swiften/Application/Application.h"
#include "Swiften/Application/ApplicationMessageDisplay.h"
+#include "Swiften/Network/TimerFactory.h"
+#include "Swiften/Network/BoostTimerFactory.h"
#include "Swift/Controllers/Chat/ChatController.h"
#include "Swift/Controllers/Chat/MUCSearchController.h"
//#include "Swift/Controllers/UIInterfaces/ChatWindowFactory.h"
@@ -183,7 +185,7 @@ void MainController::handleConnected() {
rosterController_->onChangeStatusRequest.connect(boost::bind(&MainController::handleChangeStatusRequest, this, _1, _2));
rosterController_->onSignOutRequest.connect(boost::bind(&MainController::signOut, this));
- chatsManager_ = new ChatsManager(jid_, client_, client_, eventController_, chatWindowFactory_, nickResolver_, presenceOracle_, serverDiscoInfo_, presenceSender_, uiEventStream_, chatListWindowFactory_, useDelayForLatency_);
+ chatsManager_ = new ChatsManager(jid_, client_, client_, eventController_, chatWindowFactory_, nickResolver_, presenceOracle_, serverDiscoInfo_, presenceSender_, uiEventStream_, chatListWindowFactory_, useDelayForLatency_, &timerFactory_);
nickResolver_->setMUCRegistry(chatsManager_);
client_->onMessageReceived.connect(boost::bind(&ChatsManager::handleIncomingMessage, chatsManager_, _1));
chatsManager_->setAvatarManager(avatarManager_);
diff --git a/Swiften/MUC/MUC.cpp b/Swiften/MUC/MUC.cpp
index 4390e9b..e52eae4 100644
--- a/Swiften/MUC/MUC.cpp
+++ b/Swiften/MUC/MUC.cpp
@@ -22,7 +22,11 @@ MUC::MUC(StanzaChannel* stanzaChannel, PresenceSender* presenceSender, const JID
scopedConnection_ = stanzaChannel->onPresenceReceived.connect(boost::bind(&MUC::handleIncomingPresence, this, _1));
}
+//FIXME: discover reserved nickname
+
void MUC::joinAs(const String &nick) {
+ //FIXME: password
+ //FIXME: history request
firstPresenceSeen = false;
ownMUCJID = JID(ownMUCJID.getNode(), ownMUCJID.getDomain(), nick);
@@ -45,6 +49,14 @@ void MUC::handleIncomingPresence(boost::shared_ptr<Presence> presence) {
if (!firstPresenceSeen) {
if (presence->getType() == Presence::Error) {
onJoinComplete(JoinFailed);
+ //FIXME: parse error element
+ //Wrong password
+ //Members-only
+ //Banned
+ //Nickname-conflict
+ //Max-users
+ //Locked-room
+
return;
}
firstPresenceSeen = true;
@@ -56,9 +68,19 @@ void MUC::handleIncomingPresence(boost::shared_ptr<Presence> presence) {
if (nick.isEmpty()) {
return;
}
+ //FIXME: occupant affiliation, role.
+ //FIXME: if status code='110', This is me, stop talking.
+ //FIXME: what's status 210?
+ //100 is non-anonymous
+ //FIXME: 100 may also be specified in a <message/>
+ //Once I've got my nick (110), everything new is a join
+ //170 is room logging to http
+ //FIXME: full JIDs
+ //FIXME: Nick changes
if (presence->getType() == Presence::Unavailable) {
std::map<String,MUCOccupant>::iterator i = occupants.find(nick);
if (i != occupants.end()) {
+ //FIXME: part type
onOccupantLeft(i->second, Part, "");
occupants.erase(i);
}
@@ -72,5 +94,20 @@ void MUC::handleIncomingPresence(boost::shared_ptr<Presence> presence) {
}
}
+//FIXME: Recognise Topic changes
+
+//TODO: Invites(direct/mediated)
+
+//TODO: requesting membership
+
+//TODO: get member list
+
+//TODO: request voice
+
+//TODO: moderator use cases
+
+//TODO: Admin use cases
+
+//TODO: Owner use cases
}
diff --git a/Swiften/MUC/MUC.h b/Swiften/MUC/MUC.h
index 7ee21a3..e306f11 100644
--- a/Swiften/MUC/MUC.h
+++ b/Swiften/MUC/MUC.h
@@ -26,11 +26,16 @@ namespace Swift {
public:
enum JoinResult { JoinSucceeded, JoinFailed };
enum LeavingType { Part };
+ enum Roles {Moderator, Participant, Visitor, NoRole};
+ enum Affiliations {Owner, Admin, Member, Outcast, NoAffiliation};
+
public:
MUC(StanzaChannel* stanzaChannel, PresenceSender* presenceSender, const JID &muc);
void joinAs(const String &nick);
+ /*void queryRoomInfo(); */
+ /*void queryRoomItems(); */
String getCurrentNick();
void part();
void handleIncomingMessage(boost::shared_ptr<Message> message);
@@ -39,8 +44,10 @@ namespace Swift {
boost::signal<void (JoinResult)> onJoinComplete;
boost::signal<void (boost::shared_ptr<Presence>)> onOccupantPresenceChange;
boost::signal<void (const MUCOccupant&)> onOccupantJoined;
- /**Occupant, type, and reason. */
- boost::signal<void (const MUCOccupant&, LeavingType, const String&)> onOccupantLeft;
+ boost::signal<void (const MUCOccupant&, LeavingType, const String& /*reason*/)> onOccupantLeft;
+ /* boost::signal<void (const MUCInfo&)> onInfoResult; */
+ /* boost::signal<void (const blah&)> onItemsResult; */
+
private:
bool isFromMUC(const JID& j) const {