diff options
Diffstat (limited to 'Swift/Controllers/PresenceNotifier.cpp')
-rw-r--r-- | Swift/Controllers/PresenceNotifier.cpp | 138 |
1 files changed, 138 insertions, 0 deletions
diff --git a/Swift/Controllers/PresenceNotifier.cpp b/Swift/Controllers/PresenceNotifier.cpp new file mode 100644 index 0000000..ce7ae40 --- /dev/null +++ b/Swift/Controllers/PresenceNotifier.cpp @@ -0,0 +1,138 @@ +/* + * Copyright (c) 2010 Remko Tronçon + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + +#include "Swift/Controllers/PresenceNotifier.h" + +#include <boost/bind.hpp> + +#include "Swiften/Client/StanzaChannel.h" +#include "Swiften/Base/ByteArray.h" +#include "Swiften/MUC/MUCRegistry.h" +#include "Swiften/Roster/XMPPRoster.h" +#include "Swiften/Presence/PresenceOracle.h" +#include "Swiften/Network/TimerFactory.h" + +namespace Swift { + +PresenceNotifier::PresenceNotifier(StanzaChannel* stanzaChannel, Notifier* notifier, const MUCRegistry* mucRegistry, AvatarManager* avatarManager, const XMPPRoster* roster, const PresenceOracle* presenceOracle, TimerFactory* timerFactory) : stanzaChannel(stanzaChannel), notifier(notifier), mucRegistry(mucRegistry), avatarManager(avatarManager), roster(roster), presenceOracle(presenceOracle), timerFactory(timerFactory) { + justInitialized = true; + inQuietPeriod = false; + stanzaChannel->onPresenceReceived.connect(boost::bind(&PresenceNotifier::handlePresenceReceived, this, _1)); + stanzaChannel->onAvailableChanged.connect(boost::bind(&PresenceNotifier::handleStanzaChannelAvailableChanged, this, _1)); + setInitialQuietPeriodMS(3000); +} + +PresenceNotifier::~PresenceNotifier() { + if (timer) { + timer->stop(); + timer->onTick.disconnect(boost::bind(&PresenceNotifier::handleTimerTick, this)); + timer.reset(); + } + stanzaChannel->onAvailableChanged.disconnect(boost::bind(&PresenceNotifier::handleStanzaChannelAvailableChanged, this, _1)); + stanzaChannel->onPresenceReceived.disconnect(boost::bind(&PresenceNotifier::handlePresenceReceived, this, _1)); +} + +void PresenceNotifier::handlePresenceReceived(boost::shared_ptr<Presence> presence) { + JID from = presence->getFrom(); + + if (mucRegistry->isMUC(from.toBare())) { + return; + } + + if (justInitialized) { + justInitialized = false; + if (timer) { + inQuietPeriod = true; + } + } + + if (inQuietPeriod) { + timer->stop(); + timer->start(); + return; + } + + std::set<JID>::iterator i = availableUsers.find(from); + if (presence->isAvailable()) { + if (i != availableUsers.end()) { + showNotification(from, Notifier::ContactStatusChange); + } + else { + showNotification(from, Notifier::ContactAvailable); + availableUsers.insert(from); + } + } + else { + if (i != availableUsers.end()) { + showNotification(from, Notifier::ContactUnavailable); + availableUsers.erase(i); + } + } +} + +void PresenceNotifier::handleStanzaChannelAvailableChanged(bool available) { + if (available) { + availableUsers.clear(); + justInitialized = true; + if (timer) { + timer->stop(); + } + } +} + +void PresenceNotifier::showNotification(const JID& jid, Notifier::Type type) { + String name = roster->getNameForJID(jid); + if (name.isEmpty()) { + name = jid.toBare().toString(); + } + String title = name + " (" + getStatusType(jid) + ")"; + String message = getStatusMessage(jid); + notifier->showMessage(type, title, message, avatarManager->getAvatar(jid), boost::bind(&PresenceNotifier::handleNotificationActivated, this, jid)); +} + +void PresenceNotifier::handleNotificationActivated(JID jid) { + onNotificationActivated(jid); +} + +String PresenceNotifier::getStatusType(const JID& jid) const { + Presence::ref presence = presenceOracle->getLastPresence(jid); + if (presence) { + return StatusShow::typeToFriendlyName(presence->getShow()); + } + else { + return "Unavailable"; + } +} + +String PresenceNotifier::getStatusMessage(const JID& jid) const { + Presence::ref presence = presenceOracle->getLastPresence(jid); + if (presence) { + return presence->getStatus(); + } + else { + return String(); + } +} + +void PresenceNotifier::setInitialQuietPeriodMS(int ms) { + if (timer) { + timer->stop(); + timer->onTick.disconnect(boost::bind(&PresenceNotifier::handleTimerTick, this)); + timer.reset(); + } + if (ms > 0) { + timer = timerFactory->createTimer(ms); + timer->onTick.connect(boost::bind(&PresenceNotifier::handleTimerTick, this)); + } +} + +void PresenceNotifier::handleTimerTick() { + inQuietPeriod = false; + timer->stop(); +} + + +} |