diff options
-rw-r--r-- | Swift/Controllers/Chat/ChatsManager.cpp | 5 | ||||
-rw-r--r-- | Swift/Controllers/Chat/ChatsManager.h | 4 | ||||
-rw-r--r-- | Swift/Controllers/Chat/MUCController.cpp | 35 | ||||
-rw-r--r-- | Swift/Controllers/Chat/MUCController.h | 8 | ||||
-rw-r--r-- | Swift/Controllers/MainController.cpp | 4 | ||||
-rw-r--r-- | Swiften/MUC/MUC.cpp | 37 | ||||
-rw-r--r-- | Swiften/MUC/MUC.h | 11 |
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 { |