diff --git a/src/controllers/notifications/NotificationController.cpp b/src/controllers/notifications/NotificationController.cpp index 72624991f..1b1bd2b1c 100644 --- a/src/controllers/notifications/NotificationController.cpp +++ b/src/controllers/notifications/NotificationController.cpp @@ -7,6 +7,7 @@ #include #include +#include #include namespace chatterino { @@ -15,162 +16,113 @@ void NotificationController::initialize(Settings &settings, Paths &paths) { this->initialized_ = true; for (const QString &channelName : this->twitchSetting_.getValue()) { - this->twitchVector.appendItem(channelName); + this->channelMap[Platform::Twitch].appendItem(channelName); } - this->twitchVector.delayedItemsChanged.connect([this] { // - this->twitchSetting_.setValue(this->twitchVector.getVector()); + this->channelMap[Platform::Twitch].delayedItemsChanged.connect([this] { // + this->twitchSetting_.setValue( + this->channelMap[Platform::Twitch].getVector()); }); for (const QString &channelName : this->mixerSetting_.getValue()) { - this->mixerVector.appendItem(channelName); + this->channelMap[Platform::Mixer].appendItem(channelName); } - this->mixerVector.delayedItemsChanged.connect([this] { // - this->mixerSetting_.setValue(this->mixerVector.getVector()); + this->channelMap[Platform::Mixer].delayedItemsChanged.connect([this] { // + this->mixerSetting_.setValue( + this->channelMap[Platform::Mixer].getVector()); }); } void NotificationController::updateChannelNotification( const QString &channelName, Platform p) { - if (p == Platform::Twitch) { - if (isChannelNotified(channelName, Platform::Twitch)) { - removeChannelNotification(channelName, twitchVector); - } else { - addChannelNotification(channelName, twitchVector); - } - } else if (p == Platform::Mixer) { - if (isChannelNotified(channelName, Platform::Mixer)) { - removeChannelNotification(channelName, mixerVector); - } else { - addChannelNotification(channelName, mixerVector); - } + if (isChannelNotified(channelName, p)) { + removeChannelNotification(channelName, p); + } else { + addChannelNotification(channelName, p); } } bool NotificationController::isChannelNotified(const QString &channelName, Platform p) { - /* - for (std::vector::size_type i = 0; - i != notificationVector.getVector().size(); i++) { - qDebug() << notificationVector.getVector()[i] - << " vector to the left channel to the right " << channelName - << " vectorsize:" << notificationVector.getVector().size(); + for (const auto &channel : this->channelMap[p].getVector()) { + if (channelName.toLower() == channel.toLower()) { + return true; + } } - */ - // qDebug() << channelName << " channel and now i: " << i; + // for (std::vector::size_type i = 0; i != channelMap[p]) + /* if (p == Platform::Twitch) { for (std::vector::size_type i = 0; i != twitchVector.getVector().size(); i++) { - if (twitchVector.getVector()[i] == channelName) { - return true; + if (twitchVector.getVector()[i].toLower() == + channelName.toLowercase()) { return true; } } } else if (p == Platform::Mixer) { for (std::vector::size_type i = 0; i != mixerVector.getVector().size(); i++) { - if (mixerVector.getVector()[i] == channelName) { - return true; + if (mixerVector.getVector()[i].toLower() == + channelName.toLowercase()) { return true; } } } + */ return false; } -/* -class CustomHandler : public WinToastLib::IWinToastHandler + +void NotificationController::addChannelNotification(const QString &channelName, + Platform p) { -public: - void toastActivated() const - { - std::wcout << L"The user clicked in this toast" << std::endl; - } - - void toastActivated(int actionIndex) const - { - std::wcout << L"The user clicked on button #" << actionIndex - << L" in this toast" << std::endl; - QDesktopServices::openUrl( - QUrl("http://www.google.com", QUrl::TolerantMode)); - } - - void toastFailed() const - { - std::wcout << L"Error showing current toast" << std::endl; - } - void toastDismissed(WinToastDismissalReason state) const - { - switch (state) { - case UserCanceled: - std::wcout << L"The user dismissed this toast" << std::endl; - break; - case ApplicationHidden: - std::wcout << L"The application hid the toast using " - L"ToastNotifier.hide()" - << std::endl; - break; - case TimedOut: - std::wcout << L"The toast has timed out" << std::endl; - break; - default: - std::wcout << L"Toast not activated" << std::endl; - break; - } - } -}; -*/ -void NotificationController::addChannelNotification( - const QString &channelName, UnsortedSignalVector &vector) -{ - vector.appendItem(channelName); - - if (WinToastLib::WinToast::isCompatible()) { - // QDir dir; - // qDebug() << "NaM" << dir.absolutePath(); - /* - - WinToastLib::WinToastTemplate templ = WinToastLib::WinToastTemplate( - WinToastLib::WinToastTemplate::ImageAndText02); - templ.setTextField(L"Your favorite streamer has gone live!", - WinToastLib::WinToastTemplate::FirstLine); - templ.setTextField(L"NaM!", WinToastLib::WinToastTemplate::SecondLine); - // templ.setExpiration(10); - // templ.setImagePath(); - // templ.setAudioOption(WinToastLib::WinToastTemplate::Silent); - // templ.setAudioPath(L"C:/ping2.wav"); - WinToastLib::WinToast::instance()->setAppName(L"Chatterino2"); - WinToastLib::WinToast::instance()->setAppUserModelId( - WinToastLib::WinToast::configureAUMI( - L"mohabouje", L"wintoast", L"wintoastexample", L"20161006")); - WinToastLib::WinToast::instance()->initialize(); - WinToastLib::WinToast::instance()->showToast(templ, - new CustomHandler()); - */ - } + channelMap[p].appendItem(channelName); } void NotificationController::removeChannelNotification( - const QString &channelName, UnsortedSignalVector &vector) + const QString &channelName, Platform p) { - for (std::vector::size_type i = 0; i != vector.getVector().size(); - i++) { - if (vector.getVector()[i] == channelName) { - vector.removeItem(i); + for (std::vector::size_type i = 0; + i != channelMap[p].getVector().size(); i++) { + if (channelMap[p].getVector()[i].toLower() == channelName) { + channelMap[p].removeItem(i); i--; } } } +void NotificationController::playSound() +{ + static auto player = new QMediaPlayer; + static QUrl currentPlayerUrl; + + QUrl highlightSoundUrl; + if (getApp()->settings->customHighlightSound) { + highlightSoundUrl = QUrl::fromLocalFile( + getApp()->settings->pathHighlightSound.getValue()); + } else { + highlightSoundUrl = QUrl("qrc:/sounds/ping2.wav"); + } + if (currentPlayerUrl != highlightSoundUrl) { + player->setMedia(highlightSoundUrl); + + currentPlayerUrl = highlightSoundUrl; + } + player->play(); +} + NotificationModel *NotificationController::createModel(QObject *parent, Platform p) { NotificationModel *model = new NotificationModel(parent); + model->init(&this->channelMap[p]); + /* if (p == Platform::Twitch) { model->init(&this->twitchVector); } else if (p == Platform::Mixer) { model->init(&this->mixerVector); } + */ return model; } diff --git a/src/controllers/notifications/NotificationController.hpp b/src/controllers/notifications/NotificationController.hpp index 8e7a5c974..c3bfad38f 100644 --- a/src/controllers/notifications/NotificationController.hpp +++ b/src/controllers/notifications/NotificationController.hpp @@ -22,17 +22,17 @@ public: virtual void initialize(Settings &settings, Paths &paths) override; bool isChannelNotified(const QString &channelName, Platform p); - void updateChannelNotification(const QString &channelName, Platform p); - void addChannelNotification(const QString &channelName, - UnsortedSignalVector &vector); - void removeChannelNotification(const QString &channelName, - UnsortedSignalVector &vector); + void addChannelNotification(const QString &channelName, Platform p); + void removeChannelNotification(const QString &channelName, Platform p); + + void playSound(); UnsortedSignalVector getVector(Platform p); - UnsortedSignalVector twitchVector; - UnsortedSignalVector mixerVector; + std::map> channelMap; + // UnsortedSignalVector twitchVector; + // UnsortedSignalVector mixerVector; NotificationModel *createModel(QObject *parent, Platform p); diff --git a/src/providers/twitch/TwitchChannel.cpp b/src/providers/twitch/TwitchChannel.cpp index 49147c071..39c451ec4 100644 --- a/src/providers/twitch/TwitchChannel.cpp +++ b/src/providers/twitch/TwitchChannel.cpp @@ -14,6 +14,7 @@ #include "singletons/Emotes.hpp" #include "singletons/Settings.hpp" #include "singletons/Toasts.hpp" +#include "singletons/WindowManager.hpp" #include "util/PostToThread.hpp" #include @@ -312,20 +313,20 @@ void TwitchChannel::setLive(bool newLiveStatus) auto guard = this->streamStatus_.access(); if (guard->live != newLiveStatus) { gotNewLiveStatus = true; - if (Toasts::isEnabled() && - getApp()->notifications->isChannelNotified(this->getName(), + if (getApp()->notifications->isChannelNotified(this->getName(), Platform::Twitch)) { - getApp()->toasts->sendChannelNotification(this->getName(), - Platform::Twitch); + if (Toasts::isEnabled()) { + getApp()->toasts->sendChannelNotification(this->getName(), + Platform::Twitch); + } + if (getApp()->settings->notificationPlaySound) { + getApp()->notifications->playSound(); + } + if (getApp()->settings->notificationFlashTaskbar) { + QApplication::alert( + getApp()->windows->getMainWindow().window(), 2500); + } } - /* - if (!guard->live && Toasts::isEnabled() && - getApp()->notifications->isChannelNotified( this->getName(), - Platform::Twitch)) { - getApp()->toasts->sendChannelNotification(this->getName(), - Platform::Twitch); - } - */ guard->live = newLiveStatus; } } @@ -351,7 +352,8 @@ void TwitchChannel::refreshLiveStatus() QString url("https://api.twitch.tv/kraken/streams/" + roomID); //<<<<<<< HEAD - // auto request = makeGetStreamRequest(roomID, QThread::currentThread()); + // auto request = makeGetStreamRequest(roomID, + // QThread::currentThread()); //======= auto request = NetworkRequest::twitchRequest(url); request.setCaller(QThread::currentThread()); @@ -398,7 +400,8 @@ Outcome TwitchChannel::parseLiveStatus(const rapidjson::Document &document) const rapidjson::Value &streamChannel = stream["channel"]; if (!streamChannel.IsObject() || !streamChannel.HasMember("status")) { - Log("[TwitchChannel:refreshLiveStatus] Missing member \"status\" in " + Log("[TwitchChannel:refreshLiveStatus] Missing member \"status\" " + "in " "channel"); return Failure; } @@ -407,15 +410,6 @@ Outcome TwitchChannel::parseLiveStatus(const rapidjson::Document &document) { auto status = this->streamStatus_.access(); - /* - if (!(status->live) && getApp()->toasts->isEnabled(this->getName())) { - qDebug() << " NaM xd NaM "; - int i = 0; - getApp()->toasts->sendChannelNotification(this->getName(), i); - // notifcation send - } -*/ - // status->live = true; status->viewerCount = stream["viewers"].GetUint(); status->game = stream["game"].GetString(); status->title = streamChannel["status"].GetString(); @@ -481,8 +475,8 @@ Outcome TwitchChannel::parseRecentMessages(const QJsonObject &jsonRoot) for (const auto jsonMessage : jsonMessages) { auto content = jsonMessage.toString().toUtf8(); - // passing nullptr as the channel makes the message invalid but we don't - // check for that anyways + // passing nullptr as the channel makes the message invalid but we + // don't check for that anyways auto message = Communi::IrcMessage::fromData(content, nullptr); auto privMsg = dynamic_cast(message); assert(privMsg); diff --git a/src/singletons/Toasts.cpp b/src/singletons/Toasts.cpp index 54285e009..3586944fe 100644 --- a/src/singletons/Toasts.cpp +++ b/src/singletons/Toasts.cpp @@ -18,62 +18,6 @@ namespace chatterino { -/* -Toasts::Toasts() -{ -} -*/ -/* -void Toasts::initialize(Settings &settings, Paths &paths) -{ - getApp()->twitch2->forEachChannel([this](ChannelPtr chn) { - auto twchn = dynamic_cast(chn.get()); - twchn->liveStatusChanged.connect([twchn, this]() { - const auto streamStatus = twchn->accessStreamStatus(); - if (streamStatus->live) { - // is live - if (getApp()->notifications->isChannelNotified( - twchn->getName()) && - !wasChannelLive(twchn->getName())) { - sendChannelNotification(twchn->getName()); - } - updateLiveChannels(twchn->getName()); - } else { - // is Offline - removeFromLiveChannels(twchn->getName()); - } - }); - }); -} - -void Toasts::updateLiveChannels(const QString &channelName) -{ - if (!wasChannelLive(channelName)) { - std::lock_guard lock(mutex_); - liveChannels.push_back(channelName); - } -} - -void Toasts::removeFromLiveChannels(const QString &channelName) -{ - if (wasChannelLive(channelName)) { - std::lock_guard lock(mutex_); - liveChannels.erase( - std::find(liveChannels.begin(), liveChannels.end(), channelName)); - } -} - -bool Toasts::wasChannelLive(const QString &channelName) -{ - std::lock_guard lock(mutex_); - for (const auto &str : liveChannels) { - if (str == channelName) { - return true; - } - } - return false; -} -*/ bool Toasts::isEnabled() { return WinToastLib::WinToast::isCompatible() && @@ -149,6 +93,10 @@ void Toasts::sendWindowsNotification(const QString &channelName, Platform p) templ.setTextField(widestr, WinToastLib::WinToastTemplate::FirstLine); templ.setTextField(L"Click here to open in browser", WinToastLib::WinToastTemplate::SecondLine); + if (getApp()->settings->notificationPlaySound) { + templ.setAudioOption( + WinToastLib::WinToastTemplate::AudioOption::Silent); + } WinToastLib::WinToast::instance()->setAppName(L"Chatterino2"); int mbstowcs(wchar_t * aumi_version, const char *CHATTERINO_VERSION, size_t size); diff --git a/src/singletons/Toasts.hpp b/src/singletons/Toasts.hpp index 68f7a8875..5f66d93f4 100644 --- a/src/singletons/Toasts.hpp +++ b/src/singletons/Toasts.hpp @@ -3,8 +3,6 @@ #include "Application.hpp" #include "common/Singleton.hpp" -//#include - namespace chatterino { enum class Platform : uint8_t; @@ -13,25 +11,10 @@ class Toasts final : public Singleton { public: void sendChannelNotification(const QString &channelName, Platform p); - /* - Toasts(); - virtual void initialize(Settings &settings, Paths &paths) override final; - */ + static bool isEnabled(); private: void sendWindowsNotification(const QString &channelName, Platform p); - /* - void updateLiveChannels(const QString &channelName); - void removeFromLiveChannels(const QString &channelName); - - bool wasChannelLive(const QString &channelName); - - void shouldChannelBeNotified(const QString &channelName); - void sendChannelNotification(const QString &channelName); - void sendWindowsNotification(const QString &channelName); - std::vector liveChannels; - std::mutex mutex_; - */ }; } // namespace chatterino diff --git a/src/widgets/settingspages/NotificationPage.cpp b/src/widgets/settingspages/NotificationPage.cpp index 269c1ae1e..6a0b9e55e 100644 --- a/src/widgets/settingspages/NotificationPage.cpp +++ b/src/widgets/settingspages/NotificationPage.cpp @@ -34,9 +34,10 @@ NotificationPage::NotificationPage() "Flash taskbar", getApp()->settings->notificationFlashTaskbar)); settings.append(this->createCheckBox( - "Playsound", getApp()->settings->notificationPlaySound)); + "Playsound (doesn't mute the Windows 8.x sound of toasts)", + getApp()->settings->notificationPlaySound)); settings.append(this->createCheckBox( - "Enable toasts (currently only for windows)", + "Enable toasts (currently only for windows 8.x or 10)", getApp()->settings->notificationToast)); settings->addStretch(1); @@ -62,7 +63,9 @@ NotificationPage::NotificationPage() }); view->addButtonPressed.connect([] { - getApp()->notifications->twitchVector.appendItem("channel"); + getApp() + ->notifications->channelMap[Platform::Twitch] + .appendItem("channel"); }); } auto mixerChannels = tabs.appendTab(new QVBoxLayout, "Mixer"); @@ -86,7 +89,9 @@ NotificationPage::NotificationPage() }); view->addButtonPressed.connect([] { - getApp()->notifications->mixerVector.appendItem("channel"); + getApp() + ->notifications->channelMap[Platform::Mixer] + .appendItem("channel"); }); } }