mirror of https://github.com/procxx/kepka.git
NB Broken! Notifications refactored to Manager, only Windows working.
This commit is contained in:
parent
a41e0c4aa7
commit
0bf55835f5
|
@ -42,6 +42,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
|||
#include "numbers.h"
|
||||
#include "observer_peer.h"
|
||||
#include "window/chat_background.h"
|
||||
#include "window/notifications_manager.h"
|
||||
|
||||
namespace {
|
||||
App::LaunchState _launchState = App::Launched;
|
||||
|
@ -1992,13 +1993,10 @@ namespace {
|
|||
if (::mousedItem == item) {
|
||||
mousedItem(nullptr);
|
||||
}
|
||||
if (App::wnd()) {
|
||||
App::wnd()->notifyItemRemoved(item);
|
||||
}
|
||||
}
|
||||
|
||||
void historyUnregItem(HistoryItem *item) {
|
||||
MsgsData *data = fetchMsgsData(item->channelId(), false);
|
||||
auto data = fetchMsgsData(item->channelId(), false);
|
||||
if (!data) return;
|
||||
|
||||
auto i = data->find(item->id);
|
||||
|
@ -2014,10 +2012,13 @@ namespace {
|
|||
std::swap(items, j.value());
|
||||
::dependentItems.erase(j);
|
||||
|
||||
for_const (HistoryItem *dependent, items) {
|
||||
for_const (auto dependent, items) {
|
||||
dependent->dependencyItemRemoved(item);
|
||||
}
|
||||
}
|
||||
if (auto manager = Window::Notifications::manager()) {
|
||||
manager->clearFromItem(item);
|
||||
}
|
||||
if (App::main() && !App::quitting()) {
|
||||
App::main()->itemRemoved(item);
|
||||
}
|
||||
|
|
|
@ -35,7 +35,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
|||
#include "core/observer.h"
|
||||
#include "observer_peer.h"
|
||||
#include "window/chat_background.h"
|
||||
#include "window/notifications_abstract_manager.h"
|
||||
#include "window/notifications_manager.h"
|
||||
#include "history/history_location_manager.h"
|
||||
|
||||
namespace {
|
||||
|
@ -333,6 +333,10 @@ void Application::closeApplication() {
|
|||
if (App::launchState() == App::QuitProcessed) return;
|
||||
App::setLaunchState(App::QuitProcessed);
|
||||
|
||||
if (auto manager = Window::Notifications::manager()) {
|
||||
manager->clearAllFast();
|
||||
}
|
||||
|
||||
delete AppObject;
|
||||
AppObject = 0;
|
||||
|
||||
|
|
|
@ -375,9 +375,7 @@ enum {
|
|||
WaitForChannelGetDifference = 1000, // 1s wait after show channel history before sending getChannelDifference
|
||||
|
||||
MemoryForImageCache = 64 * 1024 * 1024, // after 64mb of unpacked images we try to clear some memory
|
||||
NotifyWindowsCount = 3, // 3 desktop notifies at the same time
|
||||
NotifySettingSaveTimeout = 1000, // wait 1 second before saving notify setting to server
|
||||
NotifyDeletePhotoAfter = 60000, // delete notify photo after 1 minute
|
||||
UpdateChunk = 100 * 1024, // 100kb parts when downloading the update
|
||||
IdleMsecs = 60 * 1000, // after 60secs without user input we think we are idle
|
||||
|
||||
|
|
|
@ -479,7 +479,6 @@ void DialogsInner::removeDialog(History *history) {
|
|||
if (importantDialogs) {
|
||||
history->removeFromChatList(Dialogs::Mode::Important, importantDialogs.get());
|
||||
}
|
||||
history->clearNotifications();
|
||||
if (App::wnd()) App::wnd()->notifyClear(history);
|
||||
if (contacts->contains(history->peer->id)) {
|
||||
if (!contactsNoDialogs->contains(history->peer->id)) {
|
||||
|
|
|
@ -635,7 +635,6 @@ struct Data {
|
|||
bool IncludeMuted = true;
|
||||
DBINotifyView NotifyView = dbinvShowPreview;
|
||||
bool WindowsNotifications = true;
|
||||
bool CustomNotifies = (cPlatform() == dbipMac) ? false : true;
|
||||
base::Observable<Notify::ChangeType> NotifySettingsChanged;
|
||||
|
||||
DBIConnectionType ConnectionType = dbictAuto;
|
||||
|
@ -743,7 +742,6 @@ DefineVar(Global, bool, RestoreSoundNotifyFromTray);
|
|||
DefineVar(Global, bool, IncludeMuted);
|
||||
DefineVar(Global, DBINotifyView, NotifyView);
|
||||
DefineVar(Global, bool, WindowsNotifications);
|
||||
DefineVar(Global, bool, CustomNotifies);
|
||||
DefineRefVar(Global, base::Observable<Notify::ChangeType>, NotifySettingsChanged);
|
||||
|
||||
DefineVar(Global, DBIConnectionType, ConnectionType);
|
||||
|
|
|
@ -149,7 +149,6 @@ enum class ChangeType {
|
|||
IncludeMuted,
|
||||
DesktopEnabled,
|
||||
ViewParams,
|
||||
UseNative,
|
||||
};
|
||||
|
||||
} // namespace Notify
|
||||
|
@ -309,7 +308,6 @@ DeclareVar(bool, RestoreSoundNotifyFromTray);
|
|||
DeclareVar(bool, IncludeMuted);
|
||||
DeclareVar(DBINotifyView, NotifyView);
|
||||
DeclareVar(bool, WindowsNotifications);
|
||||
DeclareVar(bool, CustomNotifies);
|
||||
DeclareRefVar(base::Observable<Notify::ChangeType>, NotifySettingsChanged);
|
||||
|
||||
DeclareVar(DBIConnectionType, ConnectionType);
|
||||
|
|
|
@ -1427,7 +1427,6 @@ MsgId History::inboxRead(MsgId upTo) {
|
|||
|
||||
showFrom = nullptr;
|
||||
App::wnd()->notifyClear(this);
|
||||
clearNotifications();
|
||||
|
||||
return upTo;
|
||||
}
|
||||
|
|
|
@ -482,19 +482,19 @@ void HistoryMediaPtr::reset(HistoryMedia *p) {
|
|||
|
||||
namespace internal {
|
||||
|
||||
TextSelection unshiftSelection(TextSelection selection, const Text &byText) {
|
||||
if (selection == FullSelection) {
|
||||
return selection;
|
||||
}
|
||||
return ::unshiftSelection(selection, byText);
|
||||
TextSelection unshiftSelection(TextSelection selection, const Text &byText) {
|
||||
if (selection == FullSelection) {
|
||||
return selection;
|
||||
}
|
||||
return ::unshiftSelection(selection, byText);
|
||||
}
|
||||
|
||||
TextSelection shiftSelection(TextSelection selection, const Text &byText) {
|
||||
if (selection == FullSelection) {
|
||||
return selection;
|
||||
}
|
||||
return ::shiftSelection(selection, byText);
|
||||
TextSelection shiftSelection(TextSelection selection, const Text &byText) {
|
||||
if (selection == FullSelection) {
|
||||
return selection;
|
||||
}
|
||||
return ::shiftSelection(selection, byText);
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
|
||||
|
|
|
@ -436,8 +436,8 @@ private:
|
|||
|
||||
namespace internal {
|
||||
|
||||
TextSelection unshiftSelection(TextSelection selection, const Text &byText);
|
||||
TextSelection shiftSelection(TextSelection selection, const Text &byText);
|
||||
TextSelection unshiftSelection(TextSelection selection, const Text &byText);
|
||||
TextSelection shiftSelection(TextSelection selection, const Text &byText);
|
||||
|
||||
} // namespace internal
|
||||
|
||||
|
@ -837,7 +837,7 @@ public:
|
|||
|
||||
void clipCallback(Media::Clip::Notification notification);
|
||||
|
||||
virtual ~HistoryItem();
|
||||
~HistoryItem();
|
||||
|
||||
protected:
|
||||
HistoryItem(History *history, MsgId msgId, MTPDmessage::Flags flags, QDateTime msgDate, int32 from);
|
||||
|
|
|
@ -995,9 +995,6 @@ bool _readSetting(quint32 blockId, QDataStream &stream, int version) {
|
|||
if (!_checkStreamStatus(stream)) return false;
|
||||
|
||||
Global::SetWindowsNotifications(v == 1);
|
||||
if (cPlatform() == dbipWindows) {
|
||||
Global::SetCustomNotifies((App::wnd() ? !App::wnd()->psHasNativeNotifications() : true) || !Global::WindowsNotifications());
|
||||
}
|
||||
} break;
|
||||
|
||||
case dbiWorkMode: {
|
||||
|
|
|
@ -43,7 +43,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
|||
#include "localstorage.h"
|
||||
#include "apiwrap.h"
|
||||
#include "settings/settings_widget.h"
|
||||
#include "window/notifications_default_manager.h"
|
||||
#include "window/notifications_manager.h"
|
||||
|
||||
ConnectingWidget::ConnectingWidget(QWidget *parent, const QString &text, const QString &reconnect) : QWidget(parent)
|
||||
, _shadow(st::boxShadow)
|
||||
|
@ -96,8 +96,6 @@ MainWindow::MainWindow() {
|
|||
notifyClear();
|
||||
} else if (type == Notify::ChangeType::ViewParams) {
|
||||
notifyUpdateAll();
|
||||
} else if (type == Notify::ChangeType::UseNative) {
|
||||
notifyClearFast();
|
||||
} else if (type == Notify::ChangeType::IncludeMuted) {
|
||||
Notify::unreadCounterUpdated();
|
||||
}
|
||||
|
@ -118,14 +116,13 @@ MainWindow::MainWindow() {
|
|||
_inactiveTimer.setSingleShot(true);
|
||||
connect(&_inactiveTimer, SIGNAL(timeout()), this, SLOT(onInactiveTimer()));
|
||||
|
||||
connect(¬ifyWaitTimer, SIGNAL(timeout()), this, SLOT(notifyFire()));
|
||||
connect(&_notifyWaitTimer, SIGNAL(timeout()), this, SLOT(notifyShowNext()));
|
||||
|
||||
_isActiveTimer.setSingleShot(true);
|
||||
connect(&_isActiveTimer, SIGNAL(timeout()), this, SLOT(updateIsActive()));
|
||||
|
||||
connect(&_autoLockTimer, SIGNAL(timeout()), this, SLOT(checkAutoLock()));
|
||||
|
||||
subscribe(FileDownload::ImageLoaded(), [this] { notifyUpdateAllPhotos(); });
|
||||
subscribe(Global::RefSelfChanged(), [this]() { updateGlobalMenu(); });
|
||||
|
||||
setAttribute(Qt::WA_NoSystemBackground);
|
||||
|
@ -1130,72 +1127,66 @@ void MainWindow::notifySchedule(History *history, HistoryItem *item) {
|
|||
// LOG(("Is online: %1, otherOnline: %2, currentTime: %3, otherNotOld: %4, otherLaterThanMe: %5").arg(Logs::b(isOnline)).arg(cOtherOnline()).arg(t).arg(Logs::b(otherNotOld)).arg(Logs::b(otherLaterThanMe)));
|
||||
|
||||
uint64 when = ms + delay;
|
||||
notifyWhenAlerts[history].insert(when, notifyByFrom);
|
||||
_notifyWhenAlerts[history].insert(when, notifyByFrom);
|
||||
if (Global::DesktopNotify() && !psSkipDesktopNotify()) {
|
||||
NotifyWhenMaps::iterator i = notifyWhenMaps.find(history);
|
||||
if (i == notifyWhenMaps.end()) {
|
||||
i = notifyWhenMaps.insert(history, NotifyWhenMap());
|
||||
NotifyWhenMaps::iterator i = _notifyWhenMaps.find(history);
|
||||
if (i == _notifyWhenMaps.end()) {
|
||||
i = _notifyWhenMaps.insert(history, NotifyWhenMap());
|
||||
}
|
||||
if (i.value().constFind(item->id) == i.value().cend()) {
|
||||
i.value().insert(item->id, when);
|
||||
}
|
||||
NotifyWaiters *addTo = haveSetting ? ¬ifyWaiters : ¬ifySettingWaiters;
|
||||
NotifyWaiters *addTo = haveSetting ? &_notifyWaiters : &_notifySettingWaiters;
|
||||
NotifyWaiters::const_iterator it = addTo->constFind(history);
|
||||
if (it == addTo->cend() || it->when > when) {
|
||||
addTo->insert(history, NotifyWaiter(item->id, when, notifyByFrom));
|
||||
}
|
||||
}
|
||||
if (haveSetting) {
|
||||
if (!notifyWaitTimer.isActive() || notifyWaitTimer.remainingTime() > delay) {
|
||||
notifyWaitTimer.start(delay);
|
||||
if (!_notifyWaitTimer.isActive() || _notifyWaitTimer.remainingTime() > delay) {
|
||||
_notifyWaitTimer.start(delay);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::notifyFire() {
|
||||
notifyShowNext();
|
||||
}
|
||||
|
||||
void MainWindow::notifyClear(History *history) {
|
||||
if (!history) {
|
||||
for_const (auto widget, notifyWidgets) {
|
||||
widget->unlinkHistory();
|
||||
}
|
||||
psClearNotifies();
|
||||
for (NotifyWhenMaps::const_iterator i = notifyWhenMaps.cbegin(), e = notifyWhenMaps.cend(); i != e; ++i) {
|
||||
Window::Notifications::manager()->clearAll();
|
||||
|
||||
for (auto i = _notifyWhenMaps.cbegin(), e = _notifyWhenMaps.cend(); i != e; ++i) {
|
||||
i.key()->clearNotifications();
|
||||
}
|
||||
notifyWaiters.clear();
|
||||
notifySettingWaiters.clear();
|
||||
notifyWhenMaps.clear();
|
||||
_notifyWhenMaps.clear();
|
||||
_notifyWhenAlerts.clear();
|
||||
_notifyWaiters.clear();
|
||||
_notifySettingWaiters.clear();
|
||||
return;
|
||||
}
|
||||
notifyWaiters.remove(history);
|
||||
notifySettingWaiters.remove(history);
|
||||
for_const (auto widget, notifyWidgets) {
|
||||
widget->unlinkHistory(history);
|
||||
}
|
||||
psClearNotifies(history);
|
||||
notifyWhenMaps.remove(history);
|
||||
notifyWhenAlerts.remove(history);
|
||||
|
||||
Window::Notifications::manager()->clearFromHistory(history);
|
||||
|
||||
history->clearNotifications();
|
||||
_notifyWhenMaps.remove(history);
|
||||
_notifyWhenAlerts.remove(history);
|
||||
_notifyWaiters.remove(history);
|
||||
_notifySettingWaiters.remove(history);
|
||||
|
||||
_notifyWaitTimer.stop();
|
||||
notifyShowNext();
|
||||
}
|
||||
|
||||
void MainWindow::notifyClearFast() {
|
||||
notifyWaiters.clear();
|
||||
notifySettingWaiters.clear();
|
||||
for_const (auto widget, notifyWidgets) {
|
||||
widget->deleteLater();
|
||||
}
|
||||
psClearNotifies();
|
||||
notifyWidgets.clear();
|
||||
notifyWhenMaps.clear();
|
||||
notifyWhenAlerts.clear();
|
||||
Window::Notifications::manager()->clearAllFast();
|
||||
|
||||
_notifyWhenMaps.clear();
|
||||
_notifyWhenAlerts.clear();
|
||||
_notifyWaiters.clear();
|
||||
_notifySettingWaiters.clear();
|
||||
}
|
||||
|
||||
void MainWindow::notifySettingGot() {
|
||||
int32 t = unixtime();
|
||||
for (NotifyWaiters::iterator i = notifySettingWaiters.begin(); i != notifySettingWaiters.end();) {
|
||||
for (NotifyWaiters::iterator i = _notifySettingWaiters.begin(); i != _notifySettingWaiters.end();) {
|
||||
History *history = i.key();
|
||||
bool loaded = false, muted = false;
|
||||
if (history->peer->notify != UnknownNotifySettings) {
|
||||
|
@ -1224,34 +1215,24 @@ void MainWindow::notifySettingGot() {
|
|||
}
|
||||
if (loaded) {
|
||||
if (!muted) {
|
||||
notifyWaiters.insert(i.key(), i.value());
|
||||
_notifyWaiters.insert(i.key(), i.value());
|
||||
}
|
||||
i = notifySettingWaiters.erase(i);
|
||||
i = _notifySettingWaiters.erase(i);
|
||||
} else {
|
||||
++i;
|
||||
}
|
||||
}
|
||||
notifyWaitTimer.stop();
|
||||
_notifyWaitTimer.stop();
|
||||
notifyShowNext();
|
||||
}
|
||||
|
||||
void MainWindow::notifyShowNext(Window::Notifications::Widget *remove) {
|
||||
void MainWindow::notifyShowNext() {
|
||||
if (App::quitting()) return;
|
||||
|
||||
int32 count = NotifyWindowsCount;
|
||||
if (remove) {
|
||||
for (auto i = notifyWidgets.begin(), e = notifyWidgets.end(); i != e; ++i) {
|
||||
if ((*i) == remove) {
|
||||
notifyWidgets.erase(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint64 ms = getms(true), nextAlert = 0;
|
||||
bool alert = false;
|
||||
int32 now = unixtime();
|
||||
for (NotifyWhenAlerts::iterator i = notifyWhenAlerts.begin(); i != notifyWhenAlerts.end();) {
|
||||
for (NotifyWhenAlerts::iterator i = _notifyWhenAlerts.begin(); i != _notifyWhenAlerts.end();) {
|
||||
while (!i.value().isEmpty() && i.value().begin().key() <= ms) {
|
||||
NotifySettingsPtr n = i.key()->peer->notify, f = i.value().begin().value() ? i.value().begin().value()->notify : UnknownNotifySettings;
|
||||
while (!i.value().isEmpty() && i.value().begin().key() <= ms + 500) { // not more than one sound in 500ms from one peer - grouping
|
||||
|
@ -1264,7 +1245,7 @@ void MainWindow::notifyShowNext(Window::Notifications::Widget *remove) {
|
|||
}
|
||||
}
|
||||
if (i.value().isEmpty()) {
|
||||
i = notifyWhenAlerts.erase(i);
|
||||
i = _notifyWhenAlerts.erase(i);
|
||||
} else {
|
||||
if (!nextAlert || nextAlert > i.value().begin().key()) {
|
||||
nextAlert = i.value().begin().key();
|
||||
|
@ -1277,32 +1258,24 @@ void MainWindow::notifyShowNext(Window::Notifications::Widget *remove) {
|
|||
App::playSound();
|
||||
}
|
||||
|
||||
if (Global::CustomNotifies()) {
|
||||
for_const (auto widget, notifyWidgets) {
|
||||
if (widget->index() < 0) continue;
|
||||
--count;
|
||||
}
|
||||
}
|
||||
if (count <= 0 || notifyWaiters.isEmpty() || !Global::DesktopNotify() || psSkipDesktopNotify()) {
|
||||
if (_notifyWaiters.isEmpty() || !Global::DesktopNotify() || psSkipDesktopNotify()) {
|
||||
if (nextAlert) {
|
||||
notifyWaitTimer.start(nextAlert - ms);
|
||||
_notifyWaitTimer.start(nextAlert - ms);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
QRect r = psDesktopRect();
|
||||
int32 x = r.x() + r.width() - st::notifyWidth - st::notifyDeltaX, y = r.y() + r.height() - st::notifyHeight - st::notifyDeltaY;
|
||||
while (count > 0) {
|
||||
while (true) {
|
||||
uint64 next = 0;
|
||||
HistoryItem *notifyItem = 0;
|
||||
History *notifyHistory = 0;
|
||||
for (NotifyWaiters::iterator i = notifyWaiters.begin(); i != notifyWaiters.end();) {
|
||||
for (NotifyWaiters::iterator i = _notifyWaiters.begin(); i != _notifyWaiters.end();) {
|
||||
History *history = i.key();
|
||||
if (history->currentNotification() && history->currentNotification()->id != i.value().msg) {
|
||||
NotifyWhenMaps::iterator j = notifyWhenMaps.find(history);
|
||||
if (j == notifyWhenMaps.end()) {
|
||||
NotifyWhenMaps::iterator j = _notifyWhenMaps.find(history);
|
||||
if (j == _notifyWhenMaps.end()) {
|
||||
history->clearNotifications();
|
||||
i = notifyWaiters.erase(i);
|
||||
i = _notifyWaiters.erase(i);
|
||||
continue;
|
||||
}
|
||||
do {
|
||||
|
@ -1316,8 +1289,8 @@ void MainWindow::notifyShowNext(Window::Notifications::Widget *remove) {
|
|||
} while (history->currentNotification());
|
||||
}
|
||||
if (!history->currentNotification()) {
|
||||
notifyWhenMaps.remove(history);
|
||||
i = notifyWaiters.erase(i);
|
||||
_notifyWhenMaps.remove(history);
|
||||
i = _notifyWaiters.erase(i);
|
||||
continue;
|
||||
}
|
||||
uint64 when = i.value().when;
|
||||
|
@ -1334,7 +1307,7 @@ void MainWindow::notifyShowNext(Window::Notifications::Widget *remove) {
|
|||
next = nextAlert;
|
||||
nextAlert = 0;
|
||||
}
|
||||
notifyWaitTimer.start(next - ms);
|
||||
_notifyWaitTimer.start(next - ms);
|
||||
break;
|
||||
} else {
|
||||
HistoryItem *fwd = notifyItem->Has<HistoryMessageForwarded>() ? notifyItem : nullptr; // forwarded notify grouping
|
||||
|
@ -1342,8 +1315,8 @@ void MainWindow::notifyShowNext(Window::Notifications::Widget *remove) {
|
|||
|
||||
uint64 ms = getms(true);
|
||||
History *history = notifyItem->history();
|
||||
NotifyWhenMaps::iterator j = notifyWhenMaps.find(history);
|
||||
if (j == notifyWhenMaps.cend()) {
|
||||
NotifyWhenMaps::iterator j = _notifyWhenMaps.find(history);
|
||||
if (j == _notifyWhenMaps.cend()) {
|
||||
history->clearNotifications();
|
||||
} else {
|
||||
HistoryItem *nextNotify = 0;
|
||||
|
@ -1358,7 +1331,7 @@ void MainWindow::notifyShowNext(Window::Notifications::Widget *remove) {
|
|||
NotifyWhenMap::const_iterator k = j.value().constFind(history->currentNotification()->id);
|
||||
if (k != j.value().cend()) {
|
||||
nextNotify = history->currentNotification();
|
||||
notifyWaiters.insert(notifyHistory, NotifyWaiter(k.key(), k.value(), 0));
|
||||
_notifyWaiters.insert(notifyHistory, NotifyWaiter(k.key(), k.value(), 0));
|
||||
break;
|
||||
}
|
||||
history->skipNotification();
|
||||
|
@ -1379,18 +1352,11 @@ void MainWindow::notifyShowNext(Window::Notifications::Widget *remove) {
|
|||
} while (nextNotify);
|
||||
}
|
||||
|
||||
if (Global::CustomNotifies()) {
|
||||
auto widget = new Window::Notifications::Widget(notifyItem, x, y, fwdCount);
|
||||
notifyWidgets.push_back(widget);
|
||||
psNotifyShown(widget);
|
||||
--count;
|
||||
} else {
|
||||
psPlatformNotify(notifyItem, fwdCount);
|
||||
}
|
||||
Window::Notifications::manager()->showNotification(notifyItem, fwdCount);
|
||||
|
||||
if (!history->hasNotification()) {
|
||||
notifyWaiters.remove(history);
|
||||
notifyWhenMaps.remove(history);
|
||||
_notifyWaiters.remove(history);
|
||||
_notifyWhenMaps.remove(history);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
@ -1399,48 +1365,8 @@ void MainWindow::notifyShowNext(Window::Notifications::Widget *remove) {
|
|||
}
|
||||
}
|
||||
if (nextAlert) {
|
||||
notifyWaitTimer.start(nextAlert - ms);
|
||||
_notifyWaitTimer.start(nextAlert - ms);
|
||||
}
|
||||
|
||||
count = NotifyWindowsCount - count;
|
||||
for_const (auto widget, notifyWidgets) {
|
||||
if (widget->index() < 0) continue;
|
||||
--count;
|
||||
widget->moveTo(x, y - count * (st::notifyHeight + st::notifyDeltaY));
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::notifyItemRemoved(HistoryItem *item) {
|
||||
if (Global::CustomNotifies()) {
|
||||
for_const (auto widget, notifyWidgets) {
|
||||
widget->itemRemoved(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::notifyStopHiding() {
|
||||
if (Global::CustomNotifies()) {
|
||||
for_const (auto widget, notifyWidgets) {
|
||||
widget->stopHiding();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::notifyStartHiding() {
|
||||
if (Global::CustomNotifies()) {
|
||||
for_const (auto widget, notifyWidgets) {
|
||||
widget->startHiding();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::notifyUpdateAllPhotos() {
|
||||
if (Global::CustomNotifies()) {
|
||||
for_const (auto widget, notifyWidgets) {
|
||||
widget->updatePeerPhoto();
|
||||
}
|
||||
}
|
||||
if (_mediaView && !_mediaView->isHidden()) _mediaView->updateControls();
|
||||
}
|
||||
|
||||
void MainWindow::app_activateClickHandler(ClickHandlerPtr handler, Qt::MouseButton button) {
|
||||
|
@ -1448,20 +1374,7 @@ void MainWindow::app_activateClickHandler(ClickHandlerPtr handler, Qt::MouseButt
|
|||
}
|
||||
|
||||
void MainWindow::notifyUpdateAll() {
|
||||
if (Global::CustomNotifies()) {
|
||||
for_const (auto widget, notifyWidgets) {
|
||||
widget->updateNotifyDisplay();
|
||||
}
|
||||
}
|
||||
psClearNotifies();
|
||||
}
|
||||
|
||||
void MainWindow::notifyActivateAll() {
|
||||
if (Global::CustomNotifies()) {
|
||||
for_const (auto widget, notifyWidgets) {
|
||||
psActivateNotify(widget);
|
||||
}
|
||||
}
|
||||
Window::Notifications::manager()->updateAll();
|
||||
}
|
||||
|
||||
QImage MainWindow::iconLarge() const {
|
||||
|
|
|
@ -43,7 +43,9 @@ class Widget;
|
|||
|
||||
namespace Window {
|
||||
namespace Notifications {
|
||||
namespace Default {
|
||||
class Widget;
|
||||
} // namespace Default
|
||||
} // namespace Notifications
|
||||
} // namespace Window
|
||||
|
||||
|
@ -150,12 +152,7 @@ public:
|
|||
void notifySchedule(History *history, HistoryItem *item);
|
||||
void notifyClear(History *history = 0);
|
||||
void notifyClearFast();
|
||||
void notifyShowNext(Window::Notifications::Widget *remove = 0);
|
||||
void notifyItemRemoved(HistoryItem *item);
|
||||
void notifyStopHiding();
|
||||
void notifyStartHiding();
|
||||
void notifyUpdateAll();
|
||||
void notifyActivateAll();
|
||||
|
||||
QImage iconLarge() const;
|
||||
|
||||
|
@ -212,7 +209,7 @@ public slots:
|
|||
void onClearFinished(int task, void *manager);
|
||||
void onClearFailed(int task, void *manager);
|
||||
|
||||
void notifyFire();
|
||||
void notifyShowNext();
|
||||
void updateTrayMenu(bool force = false);
|
||||
|
||||
void onShowAddContact();
|
||||
|
@ -224,8 +221,6 @@ public slots:
|
|||
|
||||
void onReActivate();
|
||||
|
||||
void notifyUpdateAllPhotos();
|
||||
|
||||
void app_activateClickHandler(ClickHandlerPtr handler, Qt::MouseButton button);
|
||||
|
||||
signals:
|
||||
|
@ -277,27 +272,27 @@ private:
|
|||
SingleTimer _autoLockTimer;
|
||||
uint64 _shouldLockAt = 0;
|
||||
|
||||
typedef QMap<MsgId, uint64> NotifyWhenMap;
|
||||
typedef QMap<History*, NotifyWhenMap> NotifyWhenMaps;
|
||||
NotifyWhenMaps notifyWhenMaps;
|
||||
using NotifyWhenMap = QMap<MsgId, uint64>;
|
||||
using NotifyWhenMaps = QMap<History*, NotifyWhenMap>;
|
||||
NotifyWhenMaps _notifyWhenMaps;
|
||||
struct NotifyWaiter {
|
||||
NotifyWaiter(MsgId msg, uint64 when, PeerData *notifyByFrom) : msg(msg), when(when), notifyByFrom(notifyByFrom) {
|
||||
NotifyWaiter(MsgId msg, uint64 when, PeerData *notifyByFrom)
|
||||
: msg(msg)
|
||||
, when(when)
|
||||
, notifyByFrom(notifyByFrom) {
|
||||
}
|
||||
MsgId msg;
|
||||
uint64 when;
|
||||
PeerData *notifyByFrom;
|
||||
};
|
||||
typedef QMap<History*, NotifyWaiter> NotifyWaiters;
|
||||
NotifyWaiters notifyWaiters;
|
||||
NotifyWaiters notifySettingWaiters;
|
||||
SingleTimer notifyWaitTimer;
|
||||
using NotifyWaiters = QMap<History*, NotifyWaiter>;
|
||||
NotifyWaiters _notifyWaiters;
|
||||
NotifyWaiters _notifySettingWaiters;
|
||||
SingleTimer _notifyWaitTimer;
|
||||
|
||||
typedef QMap<uint64, PeerData*> NotifyWhenAlert;
|
||||
typedef QMap<History*, NotifyWhenAlert> NotifyWhenAlerts;
|
||||
NotifyWhenAlerts notifyWhenAlerts;
|
||||
|
||||
using NotifyWidgets = QList<Window::Notifications::Widget*>;
|
||||
NotifyWidgets notifyWidgets;
|
||||
using NotifyWhenAlert = QMap<uint64, PeerData*>;
|
||||
using NotifyWhenAlerts = QMap<History*, NotifyWhenAlert>;
|
||||
NotifyWhenAlerts _notifyWhenAlerts;
|
||||
|
||||
MediaView *_mediaView = nullptr;
|
||||
|
||||
|
|
|
@ -97,6 +97,12 @@ MediaView::MediaView() : TWidget(App::wnd())
|
|||
|
||||
connect(QApplication::desktop(), SIGNAL(resized(int)), this, SLOT(onScreenResized(int)));
|
||||
|
||||
subscribe(FileDownload::ImageLoaded(), [this] {
|
||||
if (!isHidden()) {
|
||||
updateControls();
|
||||
}
|
||||
});
|
||||
|
||||
_transparentBrush = QBrush(App::sprite().copy(st::mvTransparentBrush.rect()));
|
||||
|
||||
setWindowFlags(Qt::FramelessWindowHint | Qt::BypassWindowManagerHint | Qt::Tool | Qt::NoDropShadowWindowHint);
|
||||
|
|
|
@ -33,7 +33,7 @@ class PopupMenu;
|
|||
|
||||
struct AudioPlaybackState;
|
||||
|
||||
class MediaView : public TWidget, public RPCSender, public ClickHandlerHost {
|
||||
class MediaView : public TWidget, private base::Subscriber, public RPCSender, public ClickHandlerHost {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
|
|
@ -663,18 +663,6 @@ void MainWindow::psUpdateMargins() {
|
|||
void MainWindow::psFlash() {
|
||||
}
|
||||
|
||||
void MainWindow::psActivateNotify(Window::Notifications::Widget *w) {
|
||||
}
|
||||
|
||||
void MainWindow::psClearNotifies(PeerId peerId) {
|
||||
}
|
||||
|
||||
void MainWindow::psNotifyShown(Window::Notifications::Widget *w) {
|
||||
}
|
||||
|
||||
void MainWindow::psPlatformNotify(HistoryItem *item, int32 fwdCount) {
|
||||
}
|
||||
|
||||
MainWindow::~MainWindow() {
|
||||
if (_trayIcon) {
|
||||
Libs::g_object_unref(_trayIcon);
|
||||
|
|
|
@ -22,12 +22,6 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
|||
|
||||
#include "window/main_window.h"
|
||||
|
||||
namespace Window {
|
||||
namespace Notifications {
|
||||
class Widget;
|
||||
} // namespace Notifications
|
||||
} // namespace Window
|
||||
|
||||
namespace Platform {
|
||||
|
||||
class MainWindow : public Window::MainWindow {
|
||||
|
@ -62,11 +56,6 @@ public:
|
|||
return posInited;
|
||||
}
|
||||
|
||||
void psActivateNotify(Window::Notifications::Widget *w);
|
||||
void psClearNotifies(PeerId peerId = 0);
|
||||
void psNotifyShown(Window::Notifications::Widget *w);
|
||||
void psPlatformNotify(HistoryItem *item, int32 fwdCount);
|
||||
|
||||
void psUpdateCounter();
|
||||
|
||||
bool psHasNativeNotifications() {
|
||||
|
|
|
@ -27,7 +27,7 @@ namespace Notifications {
|
|||
void start() {
|
||||
}
|
||||
|
||||
Window::Notifications::AbstractManager *manager() {
|
||||
Window::Notifications::Manager *manager() {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
|
|
@ -20,14 +20,17 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
|||
*/
|
||||
#pragma once
|
||||
|
||||
#include "window/notifications_abstract_manager.h"
|
||||
#include "window/notifications_manager.h"
|
||||
|
||||
namespace Platform {
|
||||
namespace Notifications {
|
||||
|
||||
void start();
|
||||
Window::Notifications::AbstractManager *manager();
|
||||
Window::Notifications::Manager *manager();
|
||||
void finish();
|
||||
|
||||
inline void defaultNotificationShown(QWidget *widget) {
|
||||
}
|
||||
|
||||
} // namespace Notifications
|
||||
} // namespace Platform
|
||||
|
|
|
@ -23,12 +23,6 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
|||
#include "window/main_window.h"
|
||||
#include "pspecific_mac_p.h"
|
||||
|
||||
namespace Window {
|
||||
namespace Notifications {
|
||||
class Widget;
|
||||
} // namespace Notifications
|
||||
} // namespace Window
|
||||
|
||||
namespace Platform {
|
||||
|
||||
class MacPrivate : public PsMacWindowPrivate {
|
||||
|
@ -74,11 +68,6 @@ public:
|
|||
|
||||
bool psFilterNativeEvent(void *event);
|
||||
|
||||
void psActivateNotify(Window::Notifications::Widget *w);
|
||||
void psClearNotifies(PeerId peerId = 0);
|
||||
void psNotifyShown(Window::Notifications::Widget *w);
|
||||
void psPlatformNotify(HistoryItem *item, int32 fwdCount);
|
||||
|
||||
bool eventFilter(QObject *obj, QEvent *evt) override;
|
||||
|
||||
void psUpdateCounter();
|
||||
|
|
|
@ -24,7 +24,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
|||
#include "playerwidget.h"
|
||||
#include "historywidget.h"
|
||||
#include "localstorage.h"
|
||||
#include "window/notifications_default_manager.h"
|
||||
#include "window/notifications_manager_default.h"
|
||||
|
||||
#include "lang.h"
|
||||
|
||||
|
@ -37,8 +37,10 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
|||
namespace Platform {
|
||||
|
||||
void MacPrivate::activeSpaceChanged() {
|
||||
if (App::wnd()) {
|
||||
App::wnd()->notifyActivateAll();
|
||||
if (auto manager = Window::Notifications::Default::manager()) {
|
||||
manager->enumerateWidgets([](QWidget *widget) {
|
||||
objc_activateWnd(widget->winId());
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -464,36 +466,10 @@ void MainWindow::psFlash() {
|
|||
_private.startBounce();
|
||||
}
|
||||
|
||||
void MainWindow::psClearNotifies(PeerId peerId) {
|
||||
_private.clearNotifies(peerId);
|
||||
}
|
||||
|
||||
void MainWindow::psActivateNotify(Window::Notifications::Widget *w) {
|
||||
objc_activateWnd(w->winId());
|
||||
}
|
||||
|
||||
bool MainWindow::psFilterNativeEvent(void *event) {
|
||||
return _private.filterNativeEvent(event);
|
||||
}
|
||||
|
||||
void MainWindow::psNotifyShown(Window::Notifications::Widget *w) {
|
||||
w->hide();
|
||||
objc_holdOnTop(w->winId());
|
||||
w->show();
|
||||
psShowOverAll(w, false);
|
||||
}
|
||||
|
||||
void MainWindow::psPlatformNotify(HistoryItem *item, int32 fwdCount) {
|
||||
QString title = (!App::passcoded() && Global::NotifyView() <= dbinvShowName && !Global::ScreenIsLocked()) ? item->history()->peer->name : qsl("Telegram Desktop");
|
||||
QString subtitle = (!App::passcoded() && Global::NotifyView() <= dbinvShowName && !Global::ScreenIsLocked()) ? item->notificationHeader() : QString();
|
||||
QPixmap pix = (!App::passcoded() && Global::NotifyView() <= dbinvShowName && !Global::ScreenIsLocked()) ? item->history()->peer->genUserpic(st::notifyMacPhotoSize) : QPixmap();
|
||||
QString msg = (!App::passcoded() && Global::NotifyView() <= dbinvShowPreview && !Global::ScreenIsLocked()) ? (fwdCount < 2 ? item->notificationText() : lng_forward_messages(lt_count, fwdCount)) : lang(lng_notification_preview);
|
||||
|
||||
bool withReply = !App::passcoded() && (Global::NotifyView() <= dbinvShowPreview && !Global::ScreenIsLocked()) && item->history()->peer->canWrite();
|
||||
|
||||
_private.showNotify(item->history()->peer->id, item->id, pix, title, subtitle, msg, withReply);
|
||||
}
|
||||
|
||||
bool MainWindow::eventFilter(QObject *obj, QEvent *evt) {
|
||||
QEvent::Type t = evt->type();
|
||||
if (t == QEvent::FocusIn || t == QEvent::FocusOut) {
|
||||
|
|
|
@ -20,14 +20,31 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
|||
*/
|
||||
#pragma once
|
||||
|
||||
#include "window/notifications_abstract_manager.h"
|
||||
#include "window/notifications_manager.h"
|
||||
|
||||
namespace Platform {
|
||||
namespace Notifications {
|
||||
|
||||
void start();
|
||||
Window::Notifications::AbstractManager *manager();
|
||||
Window::Notifications::Manager *manager();
|
||||
void finish();
|
||||
|
||||
void defaultNotificationShown(QWidget *widget);
|
||||
|
||||
class Manager : public Window::Notifications::NativeManager {
|
||||
public:
|
||||
Manager();
|
||||
~Manager();
|
||||
|
||||
private:
|
||||
void doShowNativeNotification(PeerData *peer, MsgId msgId, const QString &title, const QString &subtitle, bool showUserpic, const QString &msg, bool showReplyButton) override;
|
||||
void doClearAllFast() override;
|
||||
void doClearFromHistory(History *history) override;
|
||||
|
||||
class Impl;
|
||||
std_::unique_ptr<Impl> _impl;
|
||||
|
||||
};
|
||||
|
||||
} // namespace Notifications
|
||||
} // namespace Platform
|
||||
|
|
|
@ -21,18 +21,103 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
|||
#include "stdafx.h"
|
||||
#include "platform/mac/notifications_manager_mac.h"
|
||||
|
||||
#include "pspecific.h"
|
||||
|
||||
namespace Platform {
|
||||
namespace Notifications {
|
||||
|
||||
void start() {
|
||||
}
|
||||
|
||||
Window::Notifications::AbstractManager *manager() {
|
||||
Window::Notifications::Manager *manager() {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void finish() {
|
||||
}
|
||||
|
||||
void defaultNotificationShown(QWidget *widget) {
|
||||
widget->hide();
|
||||
objc_holdOnTop(widget->winId());
|
||||
widget->show();
|
||||
psShowOverAll(w, false);
|
||||
}
|
||||
|
||||
class Manager::Impl {
|
||||
public:
|
||||
void showNotification(PeerData *peer, MsgId msgId, const QString &title, const QString &subtitle, bool showUserpic, const QString &msg, bool showReplyButton);
|
||||
void clearAll();
|
||||
void clearFromHistory(History *history);
|
||||
|
||||
~Impl();
|
||||
|
||||
private:
|
||||
|
||||
};
|
||||
|
||||
void Manager::Impl::showNotification(PeerData *peer, MsgId msgId, const QString &title, const QString &subtitle, bool showUserpic, const QString &msg, bool showReplyButton) {
|
||||
auto notification = [[NSUserNotification alloc] init];
|
||||
|
||||
[notification setUserInfo:[NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithUnsignedLongLong:peer->id],@"peer",[NSNumber numberWithInt:msgId],@"msgid",[NSNumber numberWithUnsignedLongLong:Global::LaunchId()],@"launch",nil]];
|
||||
|
||||
[notification setTitle:QNSString(title).s()];
|
||||
[notification setSubtitle:QNSString(subtitle).s()];
|
||||
[notification setInformativeText:QNSString(msg).s()];
|
||||
if (showUserpic && [notification respondsToSelector:@selector(setContentImage:)]) {
|
||||
auto userpic = peer->genUserpic(st::notifyMacPhotoSize);
|
||||
auto img = qt_mac_create_nsimage(userpic);
|
||||
[notification setContentImage:img];
|
||||
[img release];
|
||||
}
|
||||
|
||||
if (showReplyButton && [notification respondsToSelector:@selector(setHasReplyButton:)]) {
|
||||
[notification setHasReplyButton:YES];
|
||||
}
|
||||
|
||||
[notification setSoundName:nil];
|
||||
|
||||
auto center = [NSUserNotificationCenter defaultUserNotificationCenter];
|
||||
[center deliverNotification:notification];
|
||||
|
||||
[notification release];
|
||||
}
|
||||
|
||||
void Manager::Impl::clearAll() {
|
||||
auto center = [NSUserNotificationCenter defaultUserNotificationCenter];
|
||||
[center removeAllDeliveredNotifications];
|
||||
}
|
||||
|
||||
void Manager::Impl::clearFromHistory(History *history) {
|
||||
unsigned long long peerId = history->peer->id;
|
||||
|
||||
auto center = [NSUserNotificationCenter defaultUserNotificationCenter];
|
||||
auto notificationsList = [center deliveredNotifications];
|
||||
for (id notify in notificationsList) {
|
||||
auto notifyUserInfo = [notify userInfo];
|
||||
auto notifyPeerId = [[notifyUserInfo objectForKey:@"peer"] unsignedLongLongValue];
|
||||
auto notifyLaunchId = [[notifyUserInfo objectForKey:@"launch"] unsignedLongLongValue];
|
||||
if (notifyPeerId == peerId && notifyLaunchId == Global::LaunchId()) {
|
||||
[center removeDeliveredNotification:notify];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Manager::Manager() : _impl(std_::make_unique<Impl>()) {
|
||||
}
|
||||
|
||||
Manager::~Manager() = default;
|
||||
|
||||
void Manager::doShowNativeNotification(PeerData *peer, MsgId msgId, const QString &title, const QString &subtitle, bool showUserpic, const QString &msg, bool showReplyButton) {
|
||||
_impl->showNotification(peer, msgId, title, subtitle, showUserpic, msg, showReplyButton);
|
||||
}
|
||||
|
||||
void Manager::doClearAllFast() {
|
||||
_impl->clearAll();
|
||||
}
|
||||
|
||||
void Manager::doClearFromHistory(History *history) {
|
||||
_impl->clearFromHistory(history);
|
||||
}
|
||||
|
||||
} // namespace Notifications
|
||||
} // namespace Platform
|
||||
|
|
|
@ -24,7 +24,6 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
|||
|
||||
#ifdef Q_OS_MAC
|
||||
namespace Platform {
|
||||
|
||||
namespace FileDialog {
|
||||
inline bool Supported() {
|
||||
return false;
|
||||
|
|
|
@ -21,7 +21,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
|||
#pragma once
|
||||
|
||||
#ifdef Q_OS_MAC
|
||||
#include "platform/winrt/notifications_manager_mac.h"
|
||||
#include "platform/mac/notifications_manager_mac.h"
|
||||
#elif defined Q_OS_LINUX // Q_OS_MAC
|
||||
#include "platform/linux/notifications_manager_linux.h"
|
||||
#elif defined Q_OS_WINRT // Q_OS_MAC || Q_OS_LINUX
|
||||
|
|
|
@ -23,7 +23,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
|||
|
||||
#include "platform/win/windows_toasts.h"
|
||||
#include "platform/win/windows_dlls.h"
|
||||
#include "window/notifications_abstract_manager.h"
|
||||
#include "window/notifications_manager.h"
|
||||
#include "mainwindow.h"
|
||||
#include "application.h"
|
||||
#include "lang.h"
|
||||
|
@ -617,7 +617,6 @@ MainWindow::MainWindow()
|
|||
if (!_taskbarCreatedMsgId) {
|
||||
_taskbarCreatedMsgId = RegisterWindowMessage(L"TaskbarButtonCreated");
|
||||
}
|
||||
connect(&ps_cleanNotifyPhotosTimer, SIGNAL(timeout()), this, SLOT(psCleanNotifyPhotos()));
|
||||
}
|
||||
|
||||
void MainWindow::TaskbarCreated() {
|
||||
|
@ -644,22 +643,6 @@ void MainWindow::psShowTrayMenu() {
|
|||
trayIconMenu->popup(QCursor::pos());
|
||||
}
|
||||
|
||||
void MainWindow::psCleanNotifyPhotosIn(int32 dt) {
|
||||
if (dt < 0) {
|
||||
if (ps_cleanNotifyPhotosTimer.isActive() && ps_cleanNotifyPhotosTimer.remainingTime() <= -dt) return;
|
||||
dt = -dt;
|
||||
}
|
||||
ps_cleanNotifyPhotosTimer.start(dt);
|
||||
}
|
||||
|
||||
void MainWindow::psCleanNotifyPhotos() {
|
||||
auto ms = getms(true);
|
||||
auto minuntil = Toasts::clearImages(ms);
|
||||
if (minuntil) {
|
||||
psCleanNotifyPhotosIn(int32(minuntil - ms));
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::psRefreshTaskbarIcon() {
|
||||
QWidget *w = new QWidget(this);
|
||||
w->setWindowFlags(::operator|(Qt::Tool, Qt::FramelessWindowHint));
|
||||
|
@ -879,17 +862,11 @@ void MainWindow::psUpdatedPosition() {
|
|||
}
|
||||
|
||||
bool MainWindow::psHasNativeNotifications() {
|
||||
return Toasts::supported();
|
||||
return (Toasts::manager() != nullptr);
|
||||
}
|
||||
|
||||
Q_DECLARE_METATYPE(QMargins);
|
||||
void MainWindow::psFirstShow() {
|
||||
if (Toasts::supported()) {
|
||||
Global::SetCustomNotifies(!Global::WindowsNotifications());
|
||||
} else {
|
||||
Global::SetCustomNotifies(true);
|
||||
}
|
||||
|
||||
_psShadowWindows.init(_shActive);
|
||||
_shadowsWorking = true;
|
||||
|
||||
|
@ -1074,22 +1051,4 @@ MainWindow::~MainWindow() {
|
|||
if (ps_tbHider_hWnd) DestroyWindow(ps_tbHider_hWnd);
|
||||
}
|
||||
|
||||
void MainWindow::psActivateNotify(Window::Notifications::Widget *w) {
|
||||
}
|
||||
|
||||
void MainWindow::psClearNotifies(History *history) {
|
||||
if (history) {
|
||||
Window::Notifications::manager()->clearFromHistory(history);
|
||||
} else {
|
||||
Window::Notifications::manager()->clearAllFast();
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::psNotifyShown(Window::Notifications::Widget *w) {
|
||||
}
|
||||
|
||||
void MainWindow::psPlatformNotify(HistoryItem *item, int32 fwdCount) {
|
||||
Window::Notifications::manager()->showNotification(item, fwdCount);
|
||||
}
|
||||
|
||||
} // namespace Platform
|
||||
|
|
|
@ -25,12 +25,6 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
|||
|
||||
class PopupMenu;
|
||||
|
||||
namespace Window {
|
||||
namespace Notifications {
|
||||
class Widget;
|
||||
} // namespace Notifications
|
||||
} // namespace Window
|
||||
|
||||
namespace Platform {
|
||||
|
||||
class MainWindow : public Window::MainWindow {
|
||||
|
@ -67,15 +61,9 @@ public:
|
|||
return posInited;
|
||||
}
|
||||
|
||||
void psActivateNotify(Window::Notifications::Widget *w);
|
||||
void psClearNotifies(History *history = nullptr);
|
||||
void psNotifyShown(Window::Notifications::Widget *w);
|
||||
void psPlatformNotify(HistoryItem *item, int32 fwdCount);
|
||||
|
||||
void psUpdateCounter();
|
||||
|
||||
bool psHasNativeNotifications();
|
||||
void psCleanNotifyPhotosIn(int32 dt);
|
||||
|
||||
virtual QImage iconWithCounter(int size, int count, style::color bg, bool smallIcon) = 0;
|
||||
|
||||
|
@ -111,15 +99,11 @@ public:
|
|||
~MainWindow();
|
||||
|
||||
public slots:
|
||||
|
||||
void psUpdateDelegate();
|
||||
void psSavePosition(Qt::WindowState state = Qt::WindowActive);
|
||||
void psShowTrayMenu();
|
||||
|
||||
void psCleanNotifyPhotos();
|
||||
|
||||
protected:
|
||||
|
||||
bool psHasTrayIcon() const {
|
||||
return trayIcon;
|
||||
}
|
||||
|
@ -150,8 +134,6 @@ private:
|
|||
HICON ps_iconSmall = nullptr;
|
||||
HICON ps_iconOverlay = nullptr;
|
||||
|
||||
SingleTimer ps_cleanNotifyPhotosTimer;
|
||||
|
||||
int _deltaLeft = 0;
|
||||
int _deltaTop = 0;
|
||||
|
||||
|
|
|
@ -25,26 +25,20 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
|||
|
||||
namespace Platform {
|
||||
namespace Notifications {
|
||||
namespace {
|
||||
|
||||
NeverFreedPointer<Toasts::Manager> ToastsManager;
|
||||
|
||||
} // namespace
|
||||
|
||||
void start() {
|
||||
Toasts::start();
|
||||
}
|
||||
|
||||
Window::Notifications::AbstractManager *manager() {
|
||||
if (Toasts::supported()) {
|
||||
ToastsManager.makeIfNull();
|
||||
return ToastsManager.data();
|
||||
Window::Notifications::Manager *manager() {
|
||||
if (Global::WindowsNotifications()) {
|
||||
return Toasts::manager();
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void finish() {
|
||||
ToastsManager.reset();
|
||||
Toasts::finish();
|
||||
}
|
||||
|
||||
} // namespace Notifications
|
||||
|
|
|
@ -20,14 +20,17 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
|||
*/
|
||||
#pragma once
|
||||
|
||||
#include "window/notifications_abstract_manager.h"
|
||||
#include "window/notifications_manager.h"
|
||||
|
||||
namespace Platform {
|
||||
namespace Notifications {
|
||||
|
||||
void start();
|
||||
Window::Notifications::AbstractManager *manager();
|
||||
Window::Notifications::Manager *manager();
|
||||
void finish();
|
||||
|
||||
inline void defaultNotificationShown(QWidget *widget) {
|
||||
}
|
||||
|
||||
} // namespace Notifications
|
||||
} // namespace Platform
|
||||
|
|
|
@ -47,7 +47,10 @@ namespace Platform {
|
|||
namespace Toasts {
|
||||
namespace {
|
||||
|
||||
bool _supported = false;
|
||||
// Delete notify photo file after 1 minute of not using.
|
||||
constexpr int kNotifyDeletePhotoAfterMs = 60000;
|
||||
|
||||
NeverFreedPointer<Manager> ToastsManager;
|
||||
|
||||
ComPtr<IToastNotificationManagerStatics> _notificationManager;
|
||||
ComPtr<IToastNotifier> _notifier;
|
||||
|
@ -357,14 +360,18 @@ QString getImage(const StorageKey &key, PeerData *peer) {
|
|||
auto i = _images.find(key);
|
||||
if (i != _images.cend()) {
|
||||
if (i->until) {
|
||||
i->until = ms + NotifyDeletePhotoAfter;
|
||||
if (App::wnd()) App::wnd()->psCleanNotifyPhotosIn(-NotifyDeletePhotoAfter);
|
||||
i->until = ms + kNotifyDeletePhotoAfterMs;
|
||||
if (auto manager = ToastsManager.data()) {
|
||||
manager->clearNotifyPhotosInMs(-kNotifyDeletePhotoAfterMs);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Image v;
|
||||
if (key.first) {
|
||||
v.until = ms + NotifyDeletePhotoAfter;
|
||||
if (App::wnd()) App::wnd()->psCleanNotifyPhotosIn(-NotifyDeletePhotoAfter);
|
||||
v.until = ms + kNotifyDeletePhotoAfterMs;
|
||||
if (auto manager = ToastsManager.data()) {
|
||||
manager->clearNotifyPhotosInMs(-kNotifyDeletePhotoAfterMs);
|
||||
}
|
||||
} else {
|
||||
v.until = 0;
|
||||
}
|
||||
|
@ -383,14 +390,17 @@ QString getImage(const StorageKey &key, PeerData *peer) {
|
|||
} // namespace
|
||||
|
||||
void start() {
|
||||
_supported = init();
|
||||
if (init()) {
|
||||
ToastsManager.makeIfNull();
|
||||
}
|
||||
}
|
||||
|
||||
Manager *manager() {
|
||||
return ToastsManager.data();
|
||||
}
|
||||
|
||||
void finish() {
|
||||
}
|
||||
|
||||
bool supported() {
|
||||
return _supported;
|
||||
ToastsManager.reset();
|
||||
}
|
||||
|
||||
uint64 clearImages(uint64 ms) {
|
||||
|
@ -417,12 +427,15 @@ uint64 clearImages(uint64 ms) {
|
|||
|
||||
class Manager::Impl {
|
||||
public:
|
||||
bool create(PeerData *peer, MsgId msgId, const QString &title, const QString &subtitle, bool showUserpic, const QString &msg, bool showReplyButton);
|
||||
void clear(History *history, bool fast);
|
||||
bool showNotification(PeerData *peer, MsgId msgId, const QString &title, const QString &subtitle, bool showUserpic, const QString &msg, bool showReplyButton);
|
||||
void clearAll();
|
||||
void clearFromHistory(History *history);
|
||||
|
||||
~Impl();
|
||||
|
||||
private:
|
||||
QTimer _clearNotifyPhotosTimer;
|
||||
friend class Manager;
|
||||
|
||||
};
|
||||
|
||||
|
@ -437,31 +450,33 @@ Manager::Impl::~Impl() {
|
|||
}
|
||||
}
|
||||
|
||||
void Manager::Impl::clear(History *history, bool fast) {
|
||||
void Manager::Impl::clearAll() {
|
||||
if (!_notifier) return;
|
||||
|
||||
if (history) {
|
||||
auto i = _notifications.find(history->peer->id);
|
||||
if (i != _notifications.cend()) {
|
||||
auto temp = createAndSwap(i.value());
|
||||
_notifications.erase(i);
|
||||
|
||||
for (auto j = temp.cbegin(), e = temp.cend(); j != e; ++j) {
|
||||
_notifier->Hide(j->p.Get());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
auto temp = createAndSwap(_notifications);
|
||||
for_const (auto ¬ifications, temp) {
|
||||
for_const (auto ¬ification, notifications) {
|
||||
_notifier->Hide(notification.p.Get());
|
||||
}
|
||||
auto temp = createAndSwap(_notifications);
|
||||
for_const (auto ¬ifications, temp) {
|
||||
for_const (auto ¬ification, notifications) {
|
||||
_notifier->Hide(notification.p.Get());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool Manager::Impl::create(PeerData *peer, MsgId msgId, const QString &title, const QString &subtitle, bool showUserpic, const QString &msg, bool showReplyButton) {
|
||||
if (!supported() || !_notificationManager || !_notifier || !_notificationFactory) return false;
|
||||
void Manager::Impl::clearFromHistory(History *history) {
|
||||
if (!_notifier) return;
|
||||
|
||||
auto i = _notifications.find(history->peer->id);
|
||||
if (i != _notifications.cend()) {
|
||||
auto temp = createAndSwap(i.value());
|
||||
_notifications.erase(i);
|
||||
|
||||
for (auto j = temp.cbegin(), e = temp.cend(); j != e; ++j) {
|
||||
_notifier->Hide(j->p.Get());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool Manager::Impl::showNotification(PeerData *peer, MsgId msgId, const QString &title, const QString &subtitle, bool showUserpic, const QString &msg, bool showReplyButton) {
|
||||
if (!_notificationManager || !_notifier || !_notificationFactory) return false;
|
||||
|
||||
ComPtr<IXmlDocument> toastXml;
|
||||
bool withSubtitle = !subtitle.isEmpty();
|
||||
|
@ -564,16 +579,39 @@ bool Manager::Impl::create(PeerData *peer, MsgId msgId, const QString &title, co
|
|||
}
|
||||
|
||||
Manager::Manager() : _impl(std_::make_unique<Impl>()) {
|
||||
connect(&_impl->_clearNotifyPhotosTimer, SIGNAL(timeout()), this, SLOT(onClearNotifyPhotos()));
|
||||
}
|
||||
|
||||
void Manager::clearNotifyPhotosInMs(int ms) {
|
||||
if (ms < 0) {
|
||||
ms = -ms;
|
||||
if (_impl->_clearNotifyPhotosTimer.isActive() && _impl->_clearNotifyPhotosTimer.remainingTime() <= ms) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
_impl->_clearNotifyPhotosTimer.start(ms);
|
||||
}
|
||||
|
||||
void Manager::onClearNotifyPhotos() {
|
||||
auto ms = getms(true);
|
||||
auto minuntil = Toasts::clearImages(ms);
|
||||
if (minuntil) {
|
||||
clearNotifyPhotosInMs(int32(minuntil - ms));
|
||||
}
|
||||
}
|
||||
|
||||
Manager::~Manager() = default;
|
||||
|
||||
void Manager::create(PeerData *peer, MsgId msgId, const QString &title, const QString &subtitle, bool showUserpic, const QString &msg, bool showReplyButton) {
|
||||
_impl->create(peer, msgId, title, subtitle, showUserpic, msg, showReplyButton);
|
||||
void Manager::doShowNativeNotification(PeerData *peer, MsgId msgId, const QString &title, const QString &subtitle, bool showUserpic, const QString &msg, bool showReplyButton) {
|
||||
_impl->showNotification(peer, msgId, title, subtitle, showUserpic, msg, showReplyButton);
|
||||
}
|
||||
|
||||
void Manager::clear(History *history, bool fast) {
|
||||
return _impl->clear(history, fast);
|
||||
void Manager::doClearAllFast() {
|
||||
_impl->clearAll();
|
||||
}
|
||||
|
||||
void Manager::doClearFromHistory(History *history) {
|
||||
_impl->clearFromHistory(history);
|
||||
}
|
||||
|
||||
} // namespace Toasts
|
||||
|
|
|
@ -20,26 +20,37 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
|||
*/
|
||||
#pragma once
|
||||
|
||||
#include "window/notifications_abstract_manager.h"
|
||||
#include "window/notifications_manager.h"
|
||||
|
||||
namespace Platform {
|
||||
namespace Toasts {
|
||||
|
||||
class Manager;
|
||||
|
||||
void start();
|
||||
bool supported();
|
||||
Manager *manager();
|
||||
void finish();
|
||||
|
||||
// Returns the next ms when clearImages() should be called.
|
||||
uint64 clearImages(uint64 ms);
|
||||
|
||||
class Manager : public Window::Notifications::AbstractManager {
|
||||
class Manager : public QObject, public Window::Notifications::NativeManager {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
Manager();
|
||||
|
||||
void clearNotifyPhotosInMs(int ms);
|
||||
|
||||
~Manager();
|
||||
|
||||
private slots:
|
||||
void onClearNotifyPhotos();
|
||||
|
||||
private:
|
||||
void create(PeerData *peer, MsgId msgId, const QString &title, const QString &subtitle, bool showUserpic, const QString &msg, bool showReplyButton) override;
|
||||
void clear(History *history, bool fast) override;
|
||||
void doShowNativeNotification(PeerData *peer, MsgId msgId, const QString &title, const QString &subtitle, bool showUserpic, const QString &msg, bool showReplyButton) override;
|
||||
void doClearAllFast() override;
|
||||
void doClearFromHistory(History *history) override;
|
||||
|
||||
class Impl;
|
||||
std_::unique_ptr<Impl> _impl;
|
||||
|
|
|
@ -1,17 +1,17 @@
|
|||
/*
|
||||
This file is part of Telegram Desktop,
|
||||
the official desktop version of Telegram messaging app, see https://telegram.org
|
||||
|
||||
|
||||
Telegram Desktop is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
|
||||
It is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
|
||||
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
|
||||
Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||
*/
|
||||
|
@ -29,9 +29,6 @@ public:
|
|||
|
||||
void updateDelegate();
|
||||
|
||||
void showNotify(uint64 peer, int32 msgId, const QPixmap &pix, const QString &title, const QString &subtitle, const QString &msg, bool withReply);
|
||||
void clearNotifies(uint64 peer = 0);
|
||||
|
||||
void enableShadow(WId winId);
|
||||
|
||||
bool filterNativeEvent(void *event);
|
||||
|
|
|
@ -293,33 +293,6 @@ void objc_activateWnd(WId winId) {
|
|||
|
||||
NSImage *qt_mac_create_nsimage(const QPixmap &pm);
|
||||
|
||||
void PsMacWindowPrivate::showNotify(uint64 peer, int32 msgId, const QPixmap &pix, const QString &title, const QString &subtitle, const QString &msg, bool withReply) {
|
||||
NSUserNotification *notification = [[NSUserNotification alloc] init];
|
||||
NSImage *img = qt_mac_create_nsimage(pix);
|
||||
|
||||
DEBUG_LOG(("Sending notification with userinfo: peer %1, msgId %2 and instance %3").arg(peer).arg(msgId).arg(Global::LaunchId()));
|
||||
[notification setUserInfo:[NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithUnsignedLongLong:peer],@"peer",[NSNumber numberWithInt:msgId],@"msgid",[NSNumber numberWithUnsignedLongLong:Global::LaunchId()],@"launch",nil]];
|
||||
|
||||
[notification setTitle:QNSString(title).s()];
|
||||
[notification setSubtitle:QNSString(subtitle).s()];
|
||||
[notification setInformativeText:QNSString(msg).s()];
|
||||
if ([notification respondsToSelector:@selector(setContentImage:)]) {
|
||||
[notification setContentImage:img];
|
||||
}
|
||||
|
||||
if (withReply && [notification respondsToSelector:@selector(setHasReplyButton:)]) {
|
||||
[notification setHasReplyButton:YES];
|
||||
}
|
||||
|
||||
[notification setSoundName:nil];
|
||||
|
||||
NSUserNotificationCenter *center = [NSUserNotificationCenter defaultUserNotificationCenter];
|
||||
[center deliverNotification:notification];
|
||||
|
||||
if (img) [img release];
|
||||
[notification release];
|
||||
}
|
||||
|
||||
void PsMacWindowPrivate::enableShadow(WId winId) {
|
||||
// [[(NSView*)winId window] setStyleMask:NSBorderlessWindowMask];
|
||||
// [[(NSView*)winId window] setHasShadow:YES];
|
||||
|
@ -359,22 +332,6 @@ bool PsMacWindowPrivate::filterNativeEvent(void *event) {
|
|||
return false;
|
||||
}
|
||||
|
||||
|
||||
void PsMacWindowPrivate::clearNotifies(unsigned long long peer) {
|
||||
NSUserNotificationCenter *center = [NSUserNotificationCenter defaultUserNotificationCenter];
|
||||
if (peer) {
|
||||
NSArray *notifies = [center deliveredNotifications];
|
||||
for (id notify in notifies) {
|
||||
NSDictionary *dict = [notify userInfo];
|
||||
if ([[dict objectForKey:@"peer"] unsignedLongLongValue] == peer && [[dict objectForKey:@"launch"] unsignedLongLongValue] == Global::LaunchId()) {
|
||||
[center removeDeliveredNotification:notify];
|
||||
}
|
||||
}
|
||||
} else {
|
||||
[center removeAllDeliveredNotifications];
|
||||
}
|
||||
}
|
||||
|
||||
void objc_debugShowAlert(const QString &str) {
|
||||
[[NSAlert alertWithMessageText:@"Debug Message" defaultButton:@"OK" alternateButton:nil otherButton:nil informativeTextWithFormat:@"%@", QNSString(str).s()] runModal];
|
||||
}
|
||||
|
|
|
@ -27,6 +27,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
|||
#include "ui/widgets/widget_slide_wrap.h"
|
||||
#include "ui/flatcheckbox.h"
|
||||
#include "mainwindow.h"
|
||||
#include "window/notifications_manager.h"
|
||||
|
||||
namespace Settings {
|
||||
|
||||
|
@ -132,16 +133,13 @@ void NotificationsWidget::viewParamUpdated() {
|
|||
}
|
||||
|
||||
void NotificationsWidget::onWindowsNative() {
|
||||
#ifdef Q_OS_WIN
|
||||
if (Global::WindowsNotifications() == _windowsNative->checked()) {
|
||||
return;
|
||||
}
|
||||
|
||||
Window::Notifications::manager()->clearAllFast();
|
||||
Global::SetWindowsNotifications(_windowsNative->checked());
|
||||
Global::SetCustomNotifies(!Global::WindowsNotifications());
|
||||
Local::writeUserSettings();
|
||||
Global::RefNotifySettingsChanged().notify(Notify::ChangeType::UseNative);
|
||||
#endif // Q_OS_WIN
|
||||
}
|
||||
|
||||
void NotificationsWidget::onPlaySound() {
|
||||
|
|
|
@ -1,46 +0,0 @@
|
|||
/*
|
||||
This file is part of Telegram Desktop,
|
||||
the official desktop version of Telegram messaging app, see https://telegram.org
|
||||
|
||||
Telegram Desktop is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
It is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
In addition, as a special exception, the copyright holders give permission
|
||||
to link the code of portions of this program with the OpenSSL library.
|
||||
|
||||
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
|
||||
Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
namespace Window {
|
||||
namespace Notifications {
|
||||
|
||||
class AbstractManager;
|
||||
|
||||
void start();
|
||||
AbstractManager *manager();
|
||||
void finish();
|
||||
|
||||
class AbstractManager {
|
||||
public:
|
||||
void showNotification(HistoryItem *item, int forwardedCount);
|
||||
void clearAllFast();
|
||||
void clearAll();
|
||||
void clearFromHistory(History *history);
|
||||
|
||||
private:
|
||||
virtual void create(PeerData *peer, MsgId msgId, const QString &title, const QString &subtitle, bool showUserpic, const QString &msg, bool showReplyButton) = 0;
|
||||
virtual void clear(History *history, bool fast) = 0;
|
||||
|
||||
};
|
||||
|
||||
} // namespace Notifications
|
||||
} // namespace Window
|
|
@ -19,38 +19,33 @@ Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
|
|||
Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||
*/
|
||||
#include "stdafx.h"
|
||||
#include "window/notifications_abstract_manager.h"
|
||||
#include "window/notifications_manager.h"
|
||||
|
||||
#include "platform/platform_notifications_manager.h"
|
||||
#include "window/notifications_default_manager.h"
|
||||
#include "window/notifications_manager_default.h"
|
||||
#include "lang.h"
|
||||
|
||||
namespace Window {
|
||||
namespace Notifications {
|
||||
namespace {
|
||||
|
||||
NeverFreedPointer<DefaultManager> FallbackManager;
|
||||
|
||||
} // namespace
|
||||
|
||||
void start() {
|
||||
Default::start();
|
||||
Platform::Notifications::start();
|
||||
}
|
||||
|
||||
AbstractManager *manager() {
|
||||
Manager *manager() {
|
||||
if (auto result = Platform::Notifications::manager()) {
|
||||
return result;
|
||||
}
|
||||
FallbackManager.makeIfNull();
|
||||
return FallbackManager.data();
|
||||
return Default::manager();
|
||||
}
|
||||
|
||||
void finish() {
|
||||
Platform::Notifications::finish();
|
||||
FallbackManager.reset();
|
||||
Default::finish();
|
||||
}
|
||||
|
||||
void AbstractManager::showNotification(HistoryItem *item, int forwardedCount) {
|
||||
void NativeManager::doShowNotification(HistoryItem *item, int forwardedCount) {
|
||||
auto hideEverything = (App::passcoded() || Global::ScreenIsLocked());
|
||||
auto hideName = hideEverything || (Global::NotifyView() > dbinvShowName);
|
||||
auto hidePreview = hideEverything || (Global::NotifyView() > dbinvShowPreview);
|
||||
|
@ -62,19 +57,7 @@ void AbstractManager::showNotification(HistoryItem *item, int forwardedCount) {
|
|||
QString msg = hidePreview ? lang(lng_notification_preview) : (forwardedCount < 2 ? item->notificationText() : lng_forward_messages(lt_count, forwardedCount));
|
||||
bool showReplyButton = hidePreview ? false : item->history()->peer->canWrite();
|
||||
|
||||
create(item->history()->peer, item->id, title, subtitle, showUserpic, msg, showReplyButton);
|
||||
}
|
||||
|
||||
void AbstractManager::clearAllFast() {
|
||||
clear(nullptr, true);
|
||||
}
|
||||
|
||||
void AbstractManager::clearAll() {
|
||||
clear(nullptr, false);
|
||||
}
|
||||
|
||||
void AbstractManager::clearFromHistory(History *history) {
|
||||
clear(history, false);
|
||||
doShowNativeNotification(item->history()->peer, item->id, title, subtitle, showUserpic, msg, showReplyButton);
|
||||
}
|
||||
|
||||
} // namespace Notifications
|
|
@ -0,0 +1,80 @@
|
|||
/*
|
||||
This file is part of Telegram Desktop,
|
||||
the official desktop version of Telegram messaging app, see https://telegram.org
|
||||
|
||||
Telegram Desktop is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
It is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
In addition, as a special exception, the copyright holders give permission
|
||||
to link the code of portions of this program with the OpenSSL library.
|
||||
|
||||
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
|
||||
Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
namespace Window {
|
||||
namespace Notifications {
|
||||
|
||||
class Manager;
|
||||
|
||||
void start();
|
||||
Manager *manager();
|
||||
void finish();
|
||||
|
||||
class Manager {
|
||||
public:
|
||||
void showNotification(HistoryItem *item, int forwardedCount) {
|
||||
doShowNotification(item, forwardedCount);
|
||||
}
|
||||
void updateAll() {
|
||||
doUpdateAll();
|
||||
}
|
||||
void clearAll() {
|
||||
doClearAll();
|
||||
}
|
||||
void clearAllFast() {
|
||||
doClearAllFast();
|
||||
}
|
||||
void clearFromItem(HistoryItem *item) {
|
||||
doClearFromItem(item);
|
||||
}
|
||||
void clearFromHistory(History *history) {
|
||||
doClearFromHistory(history);
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual void doUpdateAll() = 0;
|
||||
virtual void doShowNotification(HistoryItem *item, int forwardedCount) = 0;
|
||||
virtual void doClearAll() = 0;
|
||||
virtual void doClearAllFast() = 0;
|
||||
virtual void doClearFromItem(HistoryItem *item) = 0;
|
||||
virtual void doClearFromHistory(History *history) = 0;
|
||||
|
||||
};
|
||||
|
||||
class NativeManager : public Manager {
|
||||
protected:
|
||||
void doUpdateAll() override {
|
||||
doClearAllFast();
|
||||
}
|
||||
void doClearAll() override {
|
||||
doClearAllFast();
|
||||
}
|
||||
void doClearFromItem(HistoryItem *item) override {
|
||||
}
|
||||
void doShowNotification(HistoryItem *item, int forwardedCount) override;
|
||||
|
||||
virtual void doShowNativeNotification(PeerData *peer, MsgId msgId, const QString &title, const QString &subtitle, bool showUserpic, const QString &msg, bool showReplyButton) = 0;
|
||||
|
||||
};
|
||||
|
||||
} // namespace Notifications
|
||||
} // namespace Window
|
|
@ -19,8 +19,9 @@ Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
|
|||
Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||
*/
|
||||
#include "stdafx.h"
|
||||
#include "window/notifications_default_manager.h"
|
||||
#include "window/notifications_manager_default.h"
|
||||
|
||||
#include "platform/platform_notifications_manager.h"
|
||||
#include "mainwindow.h"
|
||||
#include "lang.h"
|
||||
#include "dialogs/dialogs_layout.h"
|
||||
|
@ -28,45 +29,174 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
|||
|
||||
namespace Window {
|
||||
namespace Notifications {
|
||||
namespace Default {
|
||||
namespace {
|
||||
|
||||
void DefaultManager::create(PeerData *peer, MsgId msgId, const QString &title, const QString &subtitle, bool showUserpic, const QString &msg, bool showReplyButton) {
|
||||
// 3 desktop notifies at the same time.
|
||||
constexpr int kNotifyWindowsCount = 3;
|
||||
|
||||
NeverFreedPointer<Manager> FallbackManager;
|
||||
|
||||
} // namespace
|
||||
|
||||
void start() {
|
||||
FallbackManager.makeIfNull();
|
||||
}
|
||||
|
||||
void DefaultManager::clear(History *history, bool fast) {
|
||||
Manager *manager() {
|
||||
return FallbackManager.data();
|
||||
}
|
||||
|
||||
void finish() {
|
||||
FallbackManager.reset();
|
||||
}
|
||||
|
||||
Widget::Widget(HistoryItem *msg, int32 x, int32 y, int32 fwdCount) : TWidget(0)
|
||||
, history(msg->history())
|
||||
, item(msg)
|
||||
, fwdCount(fwdCount)
|
||||
Manager::Manager() {
|
||||
subscribe(FileDownload::ImageLoaded(), [this] {
|
||||
for_const (auto widget, _widgets) {
|
||||
widget->updatePeerPhoto();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void Manager::startAllHiding() {
|
||||
for_const (auto widget, _widgets) {
|
||||
widget->startHiding();
|
||||
}
|
||||
}
|
||||
|
||||
void Manager::stopAllHiding() {
|
||||
for_const (auto widget, _widgets) {
|
||||
widget->stopHiding();
|
||||
}
|
||||
}
|
||||
|
||||
void Manager::showNextFromQueue() {
|
||||
if (_queuedNotifications.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
int count = kNotifyWindowsCount;
|
||||
for_const (auto widget, _widgets) {
|
||||
if (widget->index() < 0) continue;
|
||||
--count;
|
||||
}
|
||||
if (count <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto r = psDesktopRect();
|
||||
auto x = r.x() + r.width() - st::notifyWidth - st::notifyDeltaX;
|
||||
auto y = r.y() + r.height() - st::notifyHeight - st::notifyDeltaY;
|
||||
do {
|
||||
auto queued = _queuedNotifications.front();
|
||||
_queuedNotifications.pop_front();
|
||||
|
||||
auto widget = std_::make_unique<Widget>(queued.history, queued.peer, queued.author, queued.item, queued.forwardedCount, x, y);
|
||||
Platform::Notifications::defaultNotificationShown(widget.get());
|
||||
_widgets.push_back(widget.release());
|
||||
--count;
|
||||
} while (count > 0 && !_queuedNotifications.isEmpty());
|
||||
|
||||
auto shown = kNotifyWindowsCount - count;
|
||||
for_const (auto widget, _widgets) {
|
||||
if (widget->index() < 0) continue;
|
||||
--shown;
|
||||
widget->moveTo(x, y - shown * (st::notifyHeight + st::notifyDeltaY));
|
||||
}
|
||||
}
|
||||
|
||||
void Manager::removeFromShown(Widget *remove) {
|
||||
if (remove) {
|
||||
auto index = _widgets.indexOf(remove);
|
||||
if (index >= 0) {
|
||||
_widgets.removeAt(index);
|
||||
}
|
||||
}
|
||||
showNextFromQueue();
|
||||
}
|
||||
|
||||
void Manager::doShowNotification(HistoryItem *item, int forwardedCount) {
|
||||
_queuedNotifications.push_back(QueuedNotification(item, forwardedCount));
|
||||
showNextFromQueue();
|
||||
}
|
||||
|
||||
void Manager::doClearAll() {
|
||||
_queuedNotifications.clear();
|
||||
for_const (auto widget, _widgets) {
|
||||
widget->unlinkHistory();
|
||||
}
|
||||
}
|
||||
|
||||
void Manager::doClearAllFast() {
|
||||
_queuedNotifications.clear();
|
||||
|
||||
auto widgets = createAndSwap(_widgets);
|
||||
for_const (auto widget, widgets) {
|
||||
widget->deleteLater();
|
||||
}
|
||||
}
|
||||
|
||||
void Manager::doClearFromHistory(History *history) {
|
||||
for (auto i = _queuedNotifications.begin(); i != _queuedNotifications.cend();) {
|
||||
if (i->history == history) {
|
||||
i = _queuedNotifications.erase(i);
|
||||
} else {
|
||||
++i;
|
||||
}
|
||||
}
|
||||
for_const (auto widget, _widgets) {
|
||||
widget->unlinkHistory(history);
|
||||
}
|
||||
showNextFromQueue();
|
||||
}
|
||||
|
||||
void Manager::doClearFromItem(HistoryItem *item) {
|
||||
for_const (auto widget, _widgets) {
|
||||
widget->itemRemoved(item);
|
||||
}
|
||||
}
|
||||
|
||||
void Manager::doUpdateAll() {
|
||||
for_const (auto widget, _widgets) {
|
||||
widget->updateNotifyDisplay();
|
||||
}
|
||||
}
|
||||
|
||||
Manager::~Manager() {
|
||||
clearAllFast();
|
||||
}
|
||||
|
||||
Widget::Widget(History *history, PeerData *peer, PeerData *author, HistoryItem *msg, int forwardedCount, int x, int y) : TWidget(nullptr)
|
||||
, _history(history)
|
||||
, _peer(peer)
|
||||
, _author(author)
|
||||
, _item(msg)
|
||||
, _forwardedCount(forwardedCount)
|
||||
#if defined Q_OS_WIN && !defined Q_OS_WINRT
|
||||
, started(GetTickCount())
|
||||
, _started(GetTickCount())
|
||||
#endif // Q_OS_WIN && !Q_OS_WINRT
|
||||
, close(this, st::notifyClose)
|
||||
, alphaDuration(st::notifyFastAnim)
|
||||
, posDuration(st::notifyFastAnim)
|
||||
, hiding(false)
|
||||
, _index(0)
|
||||
, _close(this, st::notifyClose)
|
||||
, _alphaDuration(st::notifyFastAnim)
|
||||
, _posDuration(st::notifyFastAnim)
|
||||
, a_opacity(0)
|
||||
, a_func(anim::linear)
|
||||
, a_y(y + st::notifyHeight + st::notifyDeltaY)
|
||||
, _a_appearance(animation(this, &Widget::step_appearance)) {
|
||||
|
||||
updateNotifyDisplay();
|
||||
|
||||
hideTimer.setSingleShot(true);
|
||||
connect(&hideTimer, SIGNAL(timeout()), this, SLOT(hideByTimer()));
|
||||
_hideTimer.setSingleShot(true);
|
||||
connect(&_hideTimer, SIGNAL(timeout()), this, SLOT(hideByTimer()));
|
||||
|
||||
inputTimer.setSingleShot(true);
|
||||
connect(&inputTimer, SIGNAL(timeout()), this, SLOT(checkLastInput()));
|
||||
_inputTimer.setSingleShot(true);
|
||||
connect(&_inputTimer, SIGNAL(timeout()), this, SLOT(checkLastInput()));
|
||||
|
||||
close.setClickedCallback([this] {
|
||||
_close.setClickedCallback([this] {
|
||||
unlinkHistoryAndNotify();
|
||||
});
|
||||
close.setAcceptBoth(true);
|
||||
close.move(st::notifyWidth - st::notifyClose.width - st::notifyClosePos.x(), st::notifyClosePos.y());
|
||||
close.show();
|
||||
_close.setAcceptBoth(true);
|
||||
_close.move(st::notifyWidth - st::notifyClose.width - st::notifyClosePos.x(), st::notifyClosePos.y());
|
||||
_close.show();
|
||||
|
||||
a_y.start(y);
|
||||
setGeometry(x, a_y.current(), st::notifyWidth, st::notifyHeight);
|
||||
|
@ -79,7 +209,7 @@ Widget::Widget(HistoryItem *msg, int32 x, int32 y, int32 fwdCount) : TWidget(0)
|
|||
|
||||
setWindowOpacity(a_opacity.current());
|
||||
|
||||
alphaDuration = posDuration = st::notifyFastAnim;
|
||||
_alphaDuration = _posDuration = st::notifyFastAnim;
|
||||
_a_appearance.start();
|
||||
|
||||
checkLastInput();
|
||||
|
@ -90,34 +220,34 @@ void Widget::checkLastInput() {
|
|||
LASTINPUTINFO lii;
|
||||
lii.cbSize = sizeof(LASTINPUTINFO);
|
||||
BOOL res = GetLastInputInfo(&lii);
|
||||
if (!res || lii.dwTime >= started) {
|
||||
hideTimer.start(st::notifyWaitLongHide);
|
||||
if (!res || lii.dwTime >= _started) {
|
||||
_hideTimer.start(st::notifyWaitLongHide);
|
||||
} else {
|
||||
inputTimer.start(300);
|
||||
_inputTimer.start(300);
|
||||
}
|
||||
#else // Q_OS_WIN && !Q_OS_WINRT
|
||||
// TODO
|
||||
if (true) {
|
||||
hideTimer.start(st::notifyWaitLongHide);
|
||||
_hideTimer.start(st::notifyWaitLongHide);
|
||||
} else {
|
||||
inputTimer.start(300);
|
||||
_inputTimer.start(300);
|
||||
}
|
||||
#endif // else for Q_OS_WIN && !Q_OS_WINRT
|
||||
}
|
||||
|
||||
void Widget::moveTo(int32 x, int32 y, int32 index) {
|
||||
void Widget::moveTo(int x, int y, int index) {
|
||||
if (index >= 0) {
|
||||
_index = index;
|
||||
}
|
||||
move(x, a_y.current());
|
||||
a_y.start(y);
|
||||
a_opacity.restart();
|
||||
posDuration = st::notifyFastAnim;
|
||||
_posDuration = st::notifyFastAnim;
|
||||
_a_appearance.start();
|
||||
}
|
||||
|
||||
void Widget::updateNotifyDisplay() {
|
||||
if (!item) return;
|
||||
if (!_history || !_peer || (!_item && _forwardedCount < 2)) return;
|
||||
|
||||
int32 w = st::notifyWidth, h = st::notifyHeight;
|
||||
QImage img(w * cIntRetinaFactor(), h * cIntRetinaFactor(), QImage::Format_ARGB32_Premultiplied);
|
||||
|
@ -132,8 +262,8 @@ void Widget::updateNotifyDisplay() {
|
|||
p.fillRect(0, st::notifyBorderWidth, st::notifyBorderWidth, h - st::notifyBorderWidth, st::notifyBorder->b);
|
||||
|
||||
if (!App::passcoded() && Global::NotifyView() <= dbinvShowName) {
|
||||
history->peer->loadUserpic(true, true);
|
||||
history->peer->paintUserpicLeft(p, st::notifyPhotoSize, st::notifyPhotoPos.x(), st::notifyPhotoPos.y(), width());
|
||||
_history->peer->loadUserpic(true, true);
|
||||
_history->peer->paintUserpicLeft(p, st::notifyPhotoSize, st::notifyPhotoPos.x(), st::notifyPhotoPos.y(), width());
|
||||
} else {
|
||||
static QPixmap icon = App::pixmapFromImageInPlace(App::wnd()->iconLarge().scaled(st::notifyPhotoSize, st::notifyPhotoSize, Qt::IgnoreAspectRatio, Qt::SmoothTransformation));
|
||||
p.drawPixmap(st::notifyPhotoPos.x(), st::notifyPhotoPos.y(), icon);
|
||||
|
@ -143,113 +273,109 @@ void Widget::updateNotifyDisplay() {
|
|||
|
||||
QRect rectForName(st::notifyPhotoPos.x() + st::notifyPhotoSize + st::notifyTextLeft, st::notifyTextTop, itemWidth, st::msgNameFont->height);
|
||||
if (!App::passcoded() && Global::NotifyView() <= dbinvShowName) {
|
||||
if (auto chatTypeIcon = Dialogs::Layout::ChatTypeIcon(history->peer, false)) {
|
||||
if (auto chatTypeIcon = Dialogs::Layout::ChatTypeIcon(_history->peer, false)) {
|
||||
chatTypeIcon->paint(p, rectForName.topLeft(), w);
|
||||
rectForName.setLeft(rectForName.left() + st::dialogsChatTypeSkip);
|
||||
}
|
||||
}
|
||||
|
||||
QDateTime now(QDateTime::currentDateTime()), lastTime(item->date);
|
||||
QDate nowDate(now.date()), lastDate(lastTime.date());
|
||||
QString dt = lastTime.toString(cTimeFormat());
|
||||
int32 dtWidth = st::dialogsTextFont->width(dt);
|
||||
rectForName.setWidth(rectForName.width() - dtWidth - st::dialogsDateSkip);
|
||||
p.setFont(st::dialogsDateFont);
|
||||
p.setPen(st::dialogsDateFg);
|
||||
p.drawText(rectForName.left() + rectForName.width() + st::dialogsDateSkip, rectForName.top() + st::dialogsTextFont->ascent, dt);
|
||||
|
||||
if (!App::passcoded() && Global::NotifyView() <= dbinvShowPreview) {
|
||||
const HistoryItem *textCachedFor = 0;
|
||||
Text itemTextCache(itemWidth);
|
||||
QRect r(st::notifyPhotoPos.x() + st::notifyPhotoSize + st::notifyTextLeft, st::notifyItemTop + st::msgNameFont->height, itemWidth, 2 * st::dialogsTextFont->height);
|
||||
if (fwdCount < 2) {
|
||||
if (_item) {
|
||||
bool active = false;
|
||||
item->drawInDialog(p, r, active, textCachedFor, itemTextCache);
|
||||
} else {
|
||||
_item->drawInDialog(p, r, active, textCachedFor, itemTextCache);
|
||||
} else if (_forwardedCount > 1) {
|
||||
p.setFont(st::dialogsTextFont);
|
||||
if (item->hasFromName() && !item->isPost()) {
|
||||
itemTextCache.setText(st::dialogsTextFont, item->author()->name);
|
||||
if (_author) {
|
||||
itemTextCache.setText(st::dialogsTextFont, _author->name);
|
||||
p.setPen(st::dialogsTextFgService);
|
||||
itemTextCache.drawElided(p, r.left(), r.top(), r.width(), st::dialogsTextFont->height);
|
||||
r.setTop(r.top() + st::dialogsTextFont->height);
|
||||
}
|
||||
p.setPen(st::dialogsTextFg);
|
||||
p.drawText(r.left(), r.top() + st::dialogsTextFont->ascent, lng_forward_messages(lt_count, fwdCount));
|
||||
p.drawText(r.left(), r.top() + st::dialogsTextFont->ascent, lng_forward_messages(lt_count, _forwardedCount));
|
||||
}
|
||||
} else {
|
||||
static QString notifyText = st::dialogsTextFont->elided(lang(lng_notification_preview), itemWidth);
|
||||
p.setFont(st::dialogsTextFont);
|
||||
p.setPen(st::dialogsTextFgService);
|
||||
p.drawText(st::notifyPhotoPos.x() + st::notifyPhotoSize + st::notifyTextLeft, st::notifyItemTop + st::msgNameFont->height + st::dialogsTextFont->ascent, notifyText);
|
||||
}
|
||||
|
||||
p.setPen(st::dialogsNameFg);
|
||||
if (!App::passcoded() && Global::NotifyView() <= dbinvShowName) {
|
||||
history->peer->dialogName().drawElided(p, rectForName.left(), rectForName.top(), rectForName.width());
|
||||
_history->peer->dialogName().drawElided(p, rectForName.left(), rectForName.top(), rectForName.width());
|
||||
} else {
|
||||
p.setFont(st::msgNameFont->f);
|
||||
p.setFont(st::msgNameFont);
|
||||
static QString notifyTitle = st::msgNameFont->elided(qsl("Telegram Desktop"), rectForName.width());
|
||||
p.drawText(rectForName.left(), rectForName.top() + st::msgNameFont->ascent, notifyTitle);
|
||||
}
|
||||
}
|
||||
|
||||
pm = App::pixmapFromImageInPlace(std_::move(img));
|
||||
_cache = App::pixmapFromImageInPlace(std_::move(img));
|
||||
update();
|
||||
}
|
||||
|
||||
void Widget::updatePeerPhoto() {
|
||||
if (!peerPhoto->isNull() && peerPhoto->loaded()) {
|
||||
QImage img(pm.toImage());
|
||||
auto img = _cache.toImage();
|
||||
{
|
||||
QPainter p(&img);
|
||||
Painter p(&img);
|
||||
p.drawPixmap(st::notifyPhotoPos.x(), st::notifyPhotoPos.y(), peerPhoto->pix(st::notifyPhotoSize));
|
||||
}
|
||||
peerPhoto = ImagePtr();
|
||||
pm = App::pixmapFromImageInPlace(std_::move(img));
|
||||
_cache = App::pixmapFromImageInPlace(std_::move(img));
|
||||
update();
|
||||
}
|
||||
}
|
||||
|
||||
void Widget::itemRemoved(HistoryItem *del) {
|
||||
if (item == del) {
|
||||
item = 0;
|
||||
void Widget::itemRemoved(HistoryItem *deleted) {
|
||||
if (_item && _item == deleted) {
|
||||
_item = nullptr;
|
||||
unlinkHistoryAndNotify();
|
||||
}
|
||||
}
|
||||
|
||||
void Widget::unlinkHistoryAndNotify() {
|
||||
unlinkHistory();
|
||||
if (auto window = App::wnd()) {
|
||||
window->notifyShowNext();
|
||||
if (auto manager = FallbackManager.data()) {
|
||||
manager->showNextFromQueue();
|
||||
}
|
||||
}
|
||||
|
||||
void Widget::unlinkHistory(History *hist) {
|
||||
if (!hist || hist == history) {
|
||||
void Widget::unlinkHistory(History *history) {
|
||||
if (!history || history == _history) {
|
||||
animHide(st::notifyFastAnim, anim::linear);
|
||||
history = 0;
|
||||
item = 0;
|
||||
_history = nullptr;
|
||||
_item = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void Widget::enterEvent(QEvent *e) {
|
||||
if (!history) return;
|
||||
if (App::wnd()) App::wnd()->notifyStopHiding();
|
||||
if (!_history) return;
|
||||
if (auto manager = FallbackManager.data()) {
|
||||
manager->stopAllHiding();
|
||||
}
|
||||
}
|
||||
|
||||
void Widget::leaveEvent(QEvent *e) {
|
||||
if (!history) return;
|
||||
App::wnd()->notifyStartHiding();
|
||||
if (!_history) return;
|
||||
if (auto manager = FallbackManager.data()) {
|
||||
manager->startAllHiding();
|
||||
}
|
||||
}
|
||||
|
||||
void Widget::startHiding() {
|
||||
hideTimer.start(st::notifyWaitShortHide);
|
||||
_hideTimer.start(st::notifyWaitShortHide);
|
||||
}
|
||||
|
||||
void Widget::mousePressEvent(QMouseEvent *e) {
|
||||
if (!history) return;
|
||||
if (!_history) return;
|
||||
|
||||
PeerId peer = history->peer->id;
|
||||
MsgId msgId = (!history->peer->isUser() && item && item->mentionsMe() && item->id > 0) ? item->id : ShowAtUnreadMsgId;
|
||||
auto peerId = _history->peer->id;
|
||||
auto msgId = (!_history->peer->isUser() && _item && _item->mentionsMe() && _item->id > 0) ? _item->id : ShowAtUnreadMsgId;
|
||||
|
||||
if (e->button() == Qt::RightButton) {
|
||||
unlinkHistoryAndNotify();
|
||||
|
@ -259,7 +385,7 @@ void Widget::mousePressEvent(QMouseEvent *e) {
|
|||
App::wnd()->setInnerFocus();
|
||||
App::wnd()->notifyClear();
|
||||
} else {
|
||||
Ui::showPeerHistory(peer, msgId);
|
||||
Ui::showPeerHistory(peerId, msgId);
|
||||
}
|
||||
e->ignore();
|
||||
}
|
||||
|
@ -267,40 +393,40 @@ void Widget::mousePressEvent(QMouseEvent *e) {
|
|||
|
||||
void Widget::paintEvent(QPaintEvent *e) {
|
||||
QPainter p(this);
|
||||
p.drawPixmap(0, 0, pm);
|
||||
p.drawPixmap(0, 0, _cache);
|
||||
}
|
||||
|
||||
void Widget::animHide(float64 duration, anim::transition func) {
|
||||
if (!history) return;
|
||||
alphaDuration = duration;
|
||||
if (!_history) return;
|
||||
_alphaDuration = duration;
|
||||
a_func = func;
|
||||
a_opacity.start(0);
|
||||
a_y.restart();
|
||||
hiding = true;
|
||||
_hiding = true;
|
||||
_a_appearance.start();
|
||||
}
|
||||
|
||||
void Widget::stopHiding() {
|
||||
if (!history) return;
|
||||
alphaDuration = st::notifyFastAnim;
|
||||
if (!_history) return;
|
||||
_alphaDuration = st::notifyFastAnim;
|
||||
a_func = anim::linear;
|
||||
a_opacity.start(1);
|
||||
a_y.restart();
|
||||
hiding = false;
|
||||
hideTimer.stop();
|
||||
_hiding = false;
|
||||
_hideTimer.stop();
|
||||
_a_appearance.start();
|
||||
}
|
||||
|
||||
void Widget::hideByTimer() {
|
||||
if (!history) return;
|
||||
if (!_history) return;
|
||||
animHide(st::notifySlowHide, st::notifySlowHideFunc);
|
||||
}
|
||||
|
||||
void Widget::step_appearance(float64 ms, bool timer) {
|
||||
float64 dtAlpha = ms / alphaDuration, dtPos = ms / posDuration;
|
||||
float64 dtAlpha = ms / _alphaDuration, dtPos = ms / _posDuration;
|
||||
if (dtAlpha >= 1) {
|
||||
a_opacity.finish();
|
||||
if (hiding) {
|
||||
if (_hiding) {
|
||||
_a_appearance.stop();
|
||||
deleteLater();
|
||||
} else if (dtPos >= 1) {
|
||||
|
@ -320,8 +446,11 @@ void Widget::step_appearance(float64 ms, bool timer) {
|
|||
}
|
||||
|
||||
Widget::~Widget() {
|
||||
if (App::wnd()) App::wnd()->notifyShowNext(this);
|
||||
if (auto manager = FallbackManager.data()) {
|
||||
manager->removeFromShown(this);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Default
|
||||
} // namespace Notifications
|
||||
} // namespace Window
|
|
@ -20,17 +20,65 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
|||
*/
|
||||
#pragma once
|
||||
|
||||
#include "window/notifications_abstract_manager.h"
|
||||
#include "window/notifications_manager.h"
|
||||
|
||||
namespace Window {
|
||||
namespace Notifications {
|
||||
namespace Default {
|
||||
|
||||
class DefaultManager : public AbstractManager {
|
||||
class Manager;
|
||||
class Widget;
|
||||
|
||||
void start();
|
||||
Manager *manager();
|
||||
void finish();
|
||||
|
||||
class Manager : public Notifications::Manager, private base::Subscriber {
|
||||
public:
|
||||
Manager();
|
||||
|
||||
void showNextFromQueue();
|
||||
void removeFromShown(Widget *remove);
|
||||
void startAllHiding();
|
||||
void stopAllHiding();
|
||||
|
||||
template <typename Method>
|
||||
void enumerateWidgets(Method method) {
|
||||
for_const (auto widget, _widgets) {
|
||||
method(widget);
|
||||
}
|
||||
}
|
||||
|
||||
~Manager();
|
||||
|
||||
private:
|
||||
void create(PeerData *peer, MsgId msgId, const QString &title, const QString &subtitle, bool showUserpic, const QString &msg, bool showReplyButton) override;
|
||||
void clear(History *history, bool fast) override;
|
||||
void doUpdateAll() override;
|
||||
void doShowNotification(HistoryItem *item, int forwardedCount) override;
|
||||
void doClearAll() override;
|
||||
void doClearAllFast() override;
|
||||
void doClearFromHistory(History *history) override;
|
||||
void doClearFromItem(HistoryItem *item) override;
|
||||
|
||||
using Widgets = QList<Widget*>;
|
||||
Widgets _widgets;
|
||||
|
||||
struct QueuedNotification {
|
||||
QueuedNotification(HistoryItem *item, int forwardedCount)
|
||||
: history(item->history())
|
||||
, peer(history->peer)
|
||||
, author((item->hasFromName() && !item->isPost()) ? item->author() : nullptr)
|
||||
, item((forwardedCount > 1) ? nullptr : item)
|
||||
, forwardedCount(forwardedCount) {
|
||||
}
|
||||
|
||||
History *history;
|
||||
PeerData *peer;
|
||||
PeerData *author;
|
||||
HistoryItem *item;
|
||||
int forwardedCount;
|
||||
};
|
||||
using QueuedNotifications = QList<QueuedNotification>;
|
||||
QueuedNotifications _queuedNotifications;
|
||||
|
||||
};
|
||||
|
||||
|
@ -38,21 +86,21 @@ class Widget : public TWidget {
|
|||
Q_OBJECT
|
||||
|
||||
public:
|
||||
Widget(HistoryItem *item, int32 x, int32 y, int32 fwdCount);
|
||||
Widget(History *history, PeerData *peer, PeerData *author, HistoryItem *item, int forwardedCount, int x, int y);
|
||||
|
||||
void step_appearance(float64 ms, bool timer);
|
||||
void animHide(float64 duration, anim::transition func);
|
||||
void startHiding();
|
||||
void stopHiding();
|
||||
void moveTo(int32 x, int32 y, int32 index = -1);
|
||||
void moveTo(int x, int y, int index = -1);
|
||||
|
||||
void updateNotifyDisplay();
|
||||
void updatePeerPhoto();
|
||||
|
||||
void itemRemoved(HistoryItem *del);
|
||||
|
||||
int32 index() const {
|
||||
return history ? _index : -1;
|
||||
int index() const {
|
||||
return _history ? _index : -1;
|
||||
}
|
||||
|
||||
void unlinkHistory(History *hist = 0);
|
||||
|
@ -73,18 +121,20 @@ private:
|
|||
void unlinkHistoryAndNotify();
|
||||
|
||||
#if defined Q_OS_WIN && !defined Q_OS_WINRT
|
||||
uint64 started;
|
||||
uint64 _started;
|
||||
#endif // Q_OS_WIN && !Q_OS_WINRT
|
||||
|
||||
History *history;
|
||||
HistoryItem *item;
|
||||
int32 fwdCount;
|
||||
IconedButton close;
|
||||
QPixmap pm;
|
||||
float64 alphaDuration, posDuration;
|
||||
QTimer hideTimer, inputTimer;
|
||||
bool hiding;
|
||||
int32 _index;
|
||||
History *_history;
|
||||
PeerData *_peer;
|
||||
PeerData *_author;
|
||||
HistoryItem *_item;
|
||||
int _forwardedCount;
|
||||
IconedButton _close;
|
||||
QPixmap _cache;
|
||||
float64 _alphaDuration, _posDuration;
|
||||
QTimer _hideTimer, _inputTimer;
|
||||
bool _hiding = false;
|
||||
int _index = 0;
|
||||
anim::fvalue a_opacity;
|
||||
anim::transition a_func;
|
||||
anim::ivalue a_y;
|
||||
|
@ -94,5 +144,6 @@ private:
|
|||
|
||||
};
|
||||
|
||||
} // namespace Default
|
||||
} // namespace Notifications
|
||||
} // namespace Window
|
|
@ -482,10 +482,10 @@
|
|||
'<(src_loc)/window/chat_background.h',
|
||||
'<(src_loc)/window/main_window.cpp',
|
||||
'<(src_loc)/window/main_window.h',
|
||||
'<(src_loc)/window/notifications_abstract_manager.cpp',
|
||||
'<(src_loc)/window/notifications_abstract_manager.h',
|
||||
'<(src_loc)/window/notifications_default_manager.cpp',
|
||||
'<(src_loc)/window/notifications_default_manager.h',
|
||||
'<(src_loc)/window/notifications_manager.cpp',
|
||||
'<(src_loc)/window/notifications_manager.h',
|
||||
'<(src_loc)/window/notifications_manager_default.cpp',
|
||||
'<(src_loc)/window/notifications_manager_default.h',
|
||||
'<(src_loc)/window/section_widget.cpp',
|
||||
'<(src_loc)/window/section_widget.h',
|
||||
'<(src_loc)/window/slide_animation.cpp',
|
||||
|
|
Loading…
Reference in New Issue