mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-06-05 06:33:57 +02:00
Notifications management moved to AuthSession.
Also implemented Global::WorkMode() as an base::Variable.
This commit is contained in:
parent
b14ba398e6
commit
81790b2271
80 changed files with 1299 additions and 1152 deletions
|
@ -31,6 +31,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||||
#include "auth_session.h"
|
#include "auth_session.h"
|
||||||
#include "boxes/confirmbox.h"
|
#include "boxes/confirmbox.h"
|
||||||
#include "window/themes/window_theme.h"
|
#include "window/themes/window_theme.h"
|
||||||
|
#include "window/notifications_manager.h"
|
||||||
|
|
||||||
ApiWrap::ApiWrap(QObject *parent) : QObject(parent)
|
ApiWrap::ApiWrap(QObject *parent) : QObject(parent)
|
||||||
, _messageDataResolveDelayed(new SingleDelayedCall(this, "resolveMessageDatas")) {
|
, _messageDataResolveDelayed(new SingleDelayedCall(this, "resolveMessageDatas")) {
|
||||||
|
@ -1016,7 +1017,7 @@ PeerData *ApiWrap::notifySettingReceived(MTPInputNotifyPeer notifyPeer, const MT
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
}
|
}
|
||||||
App::wnd()->notifySettingGot();
|
AuthSession::Current().notifications()->checkDelayed();
|
||||||
return requestedPeer;
|
return requestedPeer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -203,15 +203,14 @@ namespace {
|
||||||
Media::Player::mixer()->stopAndClear();
|
Media::Player::mixer()->stopAndClear();
|
||||||
if (auto w = wnd()) {
|
if (auto w = wnd()) {
|
||||||
w->tempDirDelete(Local::ClearManagerAll);
|
w->tempDirDelete(Local::ClearManagerAll);
|
||||||
w->notifyClearFast();
|
|
||||||
w->setupIntro();
|
w->setupIntro();
|
||||||
}
|
}
|
||||||
|
histories().clear();
|
||||||
Messenger::Instance().authSessionDestroy();
|
Messenger::Instance().authSessionDestroy();
|
||||||
Local::reset();
|
Local::reset();
|
||||||
Window::Theme::Background()->reset();
|
Window::Theme::Background()->reset();
|
||||||
|
|
||||||
cSetOtherOnline(0);
|
cSetOtherOnline(0);
|
||||||
histories().clear();
|
|
||||||
globalNotifyAllPtr = UnknownNotifySettings;
|
globalNotifyAllPtr = UnknownNotifySettings;
|
||||||
globalNotifyUsersPtr = UnknownNotifySettings;
|
globalNotifyUsersPtr = UnknownNotifySettings;
|
||||||
globalNotifyChatsPtr = UnknownNotifySettings;
|
globalNotifyChatsPtr = UnknownNotifySettings;
|
||||||
|
@ -2014,9 +2013,7 @@ namespace {
|
||||||
dependent->dependencyItemRemoved(item);
|
dependent->dependencyItemRemoved(item);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (auto manager = Window::Notifications::GetManager()) {
|
AuthSession::Current().notifications()->clearFromItem(item);
|
||||||
manager->clearFromItem(item);
|
|
||||||
}
|
|
||||||
if (Global::started() && !App::quitting()) {
|
if (Global::started() && !App::quitting()) {
|
||||||
Global::RefItemRemoved().notify(item, true);
|
Global::RefItemRemoved().notify(item, true);
|
||||||
}
|
}
|
||||||
|
@ -2038,13 +2035,13 @@ namespace {
|
||||||
::dependentItems.clear();
|
::dependentItems.clear();
|
||||||
|
|
||||||
QVector<HistoryItem*> toDelete;
|
QVector<HistoryItem*> toDelete;
|
||||||
for_const (HistoryItem *item, msgsData) {
|
for_const (auto item, msgsData) {
|
||||||
if (item->detached()) {
|
if (item->detached()) {
|
||||||
toDelete.push_back(item);
|
toDelete.push_back(item);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for_const (const MsgsData &chMsgsData, channelMsgsData) {
|
for_const (auto &chMsgsData, channelMsgsData) {
|
||||||
for_const (HistoryItem *item, chMsgsData) {
|
for_const (auto item, chMsgsData) {
|
||||||
if (item->detached()) {
|
if (item->detached()) {
|
||||||
toDelete.push_back(item);
|
toDelete.push_back(item);
|
||||||
}
|
}
|
||||||
|
@ -2052,8 +2049,8 @@ namespace {
|
||||||
}
|
}
|
||||||
msgsData.clear();
|
msgsData.clear();
|
||||||
channelMsgsData.clear();
|
channelMsgsData.clear();
|
||||||
for (int32 i = 0, l = toDelete.size(); i < l; ++i) {
|
for_const (auto item, toDelete) {
|
||||||
delete toDelete[i];
|
delete item;
|
||||||
}
|
}
|
||||||
|
|
||||||
clearMousedItems();
|
clearMousedItems();
|
||||||
|
|
|
@ -319,10 +319,6 @@ void Application::closeApplication() {
|
||||||
if (App::launchState() == App::QuitProcessed) return;
|
if (App::launchState() == App::QuitProcessed) return;
|
||||||
App::setLaunchState(App::QuitProcessed);
|
App::setLaunchState(App::QuitProcessed);
|
||||||
|
|
||||||
if (auto manager = Window::Notifications::GetManager()) {
|
|
||||||
manager->clearAllFast();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_messengerInstance) {
|
if (_messengerInstance) {
|
||||||
Messenger::Instance().prepareToDestroy();
|
Messenger::Instance().prepareToDestroy();
|
||||||
_messengerInstance.reset();
|
_messengerInstance.reset();
|
||||||
|
|
|
@ -21,18 +21,41 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||||
#include "auth_session.h"
|
#include "auth_session.h"
|
||||||
|
|
||||||
#include "messenger.h"
|
#include "messenger.h"
|
||||||
|
#include "storage/file_download.h"
|
||||||
|
#include "window/notifications_manager.h"
|
||||||
|
|
||||||
AuthSession::AuthSession(UserId userId) : _userId(userId) {
|
AuthSession::AuthSession(UserId userId)
|
||||||
|
: _userId(userId)
|
||||||
|
, _downloader(std::make_unique<Storage::Downloader>())
|
||||||
|
, _notifications(std::make_unique<Window::Notifications::System>(this)) {
|
||||||
t_assert(_userId != 0);
|
t_assert(_userId != 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
AuthSession *AuthSession::Current() {
|
bool AuthSession::Exists() {
|
||||||
return Messenger::Instance().authSession();
|
return (Messenger::Instance().authSession() != nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
AuthSession &AuthSession::Current() {
|
||||||
|
auto result = Messenger::Instance().authSession();
|
||||||
|
t_assert(result != nullptr);
|
||||||
|
return *result;
|
||||||
}
|
}
|
||||||
|
|
||||||
UserData *AuthSession::CurrentUser() {
|
UserData *AuthSession::CurrentUser() {
|
||||||
if (auto userId = CurrentUserId()) {
|
return App::user(CurrentUserId());
|
||||||
return App::user(userId);
|
|
||||||
}
|
|
||||||
return nullptr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
base::Observable<void> &AuthSession::CurrentDownloaderTaskFinished() {
|
||||||
|
return Current().downloader()->taskFinished();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AuthSession::validateSelf(const MTPUser &user) {
|
||||||
|
if (user.type() != mtpc_user || !user.c_user().is_self() || user.c_user().vid.v != userId()) {
|
||||||
|
LOG(("Auth Error: wrong self user received."));
|
||||||
|
App::logOutDelayed();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
AuthSession::~AuthSession() = default;
|
||||||
|
|
|
@ -20,29 +20,55 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||||
*/
|
*/
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
class AuthSession {
|
namespace Storage {
|
||||||
|
class Downloader;
|
||||||
|
} // namespace Storage
|
||||||
|
|
||||||
|
namespace Window {
|
||||||
|
namespace Notifications {
|
||||||
|
class System;
|
||||||
|
} // namespace Notifications
|
||||||
|
} // namespace Window
|
||||||
|
|
||||||
|
class AuthSession final {
|
||||||
public:
|
public:
|
||||||
AuthSession(UserId userId);
|
AuthSession(UserId userId);
|
||||||
|
|
||||||
AuthSession(const AuthSession &other) = delete;
|
AuthSession(const AuthSession &other) = delete;
|
||||||
AuthSession &operator=(const AuthSession &other) = delete;
|
AuthSession &operator=(const AuthSession &other) = delete;
|
||||||
|
|
||||||
static AuthSession *Current();
|
static bool Exists();
|
||||||
|
|
||||||
|
static AuthSession &Current();
|
||||||
static UserId CurrentUserId() {
|
static UserId CurrentUserId() {
|
||||||
auto current = Current();
|
return Current().userId();
|
||||||
return current ? current->userId() : 0;
|
|
||||||
}
|
}
|
||||||
static PeerId CurrentUserPeerId() {
|
static PeerId CurrentUserPeerId() {
|
||||||
auto userId = CurrentUserId();
|
return peerFromUser(CurrentUserId());
|
||||||
return userId ? peerFromUser(userId) : 0;
|
|
||||||
}
|
}
|
||||||
static UserData *CurrentUser();
|
static UserData *CurrentUser();
|
||||||
|
|
||||||
UserId userId() const {
|
UserId userId() const {
|
||||||
return _userId;
|
return _userId;
|
||||||
}
|
}
|
||||||
|
bool validateSelf(const MTPUser &user);
|
||||||
|
|
||||||
|
Storage::Downloader *downloader() {
|
||||||
|
return _downloader.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
static base::Observable<void> &CurrentDownloaderTaskFinished();
|
||||||
|
|
||||||
|
Window::Notifications::System *notifications() {
|
||||||
|
return _notifications.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
~AuthSession();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
UserId _userId = 0;
|
UserId _userId = 0;
|
||||||
|
|
||||||
|
const std::unique_ptr<Storage::Downloader> _downloader;
|
||||||
|
const std::unique_ptr<Window::Notifications::System> _notifications;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -38,6 +38,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||||
#include "mainwindow.h"
|
#include "mainwindow.h"
|
||||||
#include "apiwrap.h"
|
#include "apiwrap.h"
|
||||||
#include "observer_peer.h"
|
#include "observer_peer.h"
|
||||||
|
#include "auth_session.h"
|
||||||
|
|
||||||
AddContactBox::AddContactBox(QWidget*, QString fname, QString lname, QString phone)
|
AddContactBox::AddContactBox(QWidget*, QString fname, QString lname, QString phone)
|
||||||
: _first(this, st::defaultInputField, lang(lng_signup_firstname), fname)
|
: _first(this, st::defaultInputField, lang(lng_signup_firstname), fname)
|
||||||
|
@ -1119,7 +1120,7 @@ void RevokePublicLinkBox::prepare() {
|
||||||
|
|
||||||
addButton(lang(lng_cancel), [this] { closeBox(); });
|
addButton(lang(lng_cancel), [this] { closeBox(); });
|
||||||
|
|
||||||
subscribe(FileDownload::ImageLoaded(), [this] { update(); });
|
subscribe(AuthSession::CurrentDownloaderTaskFinished(), [this] { update(); });
|
||||||
|
|
||||||
updateMaxHeight();
|
updateMaxHeight();
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,6 +27,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||||
#include "styles/style_overview.h"
|
#include "styles/style_overview.h"
|
||||||
#include "styles/style_boxes.h"
|
#include "styles/style_boxes.h"
|
||||||
#include "ui/effects/round_checkbox.h"
|
#include "ui/effects/round_checkbox.h"
|
||||||
|
#include "auth_session.h"
|
||||||
|
|
||||||
BackgroundBox::BackgroundBox(QWidget*) {
|
BackgroundBox::BackgroundBox(QWidget*) {
|
||||||
}
|
}
|
||||||
|
@ -63,7 +64,7 @@ BackgroundBox::Inner::Inner(QWidget *parent) : TWidget(parent)
|
||||||
updateWallpapers();
|
updateWallpapers();
|
||||||
}
|
}
|
||||||
|
|
||||||
subscribe(FileDownload::ImageLoaded(), [this] { update(); });
|
subscribe(AuthSession::CurrentDownloaderTaskFinished(), [this] { update(); });
|
||||||
subscribe(Window::Theme::Background(), [this](const Window::Theme::BackgroundUpdate &update) {
|
subscribe(Window::Theme::Background(), [this](const Window::Theme::BackgroundUpdate &update) {
|
||||||
if (update.paletteChanged()) {
|
if (update.paletteChanged()) {
|
||||||
_check->invalidateCache();
|
_check->invalidateCache();
|
||||||
|
|
|
@ -32,6 +32,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||||
#include "ui/toast/toast.h"
|
#include "ui/toast/toast.h"
|
||||||
#include "core/click_handler_types.h"
|
#include "core/click_handler_types.h"
|
||||||
#include "storage/localstorage.h"
|
#include "storage/localstorage.h"
|
||||||
|
#include "auth_session.h"
|
||||||
|
|
||||||
TextParseOptions _confirmBoxTextOptions = {
|
TextParseOptions _confirmBoxTextOptions = {
|
||||||
TextParseLinks | TextParseMultiline | TextParseRichText, // flags
|
TextParseLinks | TextParseMultiline | TextParseRichText, // flags
|
||||||
|
@ -569,7 +570,7 @@ ConfirmInviteBox::ConfirmInviteBox(QWidget*, const QString &title, const MTPChat
|
||||||
if (!location.isNull()) {
|
if (!location.isNull()) {
|
||||||
_photo = ImagePtr(location);
|
_photo = ImagePtr(location);
|
||||||
if (!_photo->loaded()) {
|
if (!_photo->loaded()) {
|
||||||
subscribe(FileDownload::ImageLoaded(), [this] { update(); });
|
subscribe(AuthSession::CurrentDownloaderTaskFinished(), [this] { update(); });
|
||||||
_photo->load();
|
_photo->load();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,6 +43,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||||
#include "observer_peer.h"
|
#include "observer_peer.h"
|
||||||
#include "apiwrap.h"
|
#include "apiwrap.h"
|
||||||
#include "auth_session.h"
|
#include "auth_session.h"
|
||||||
|
#include "storage/file_download.h"
|
||||||
|
|
||||||
QString PeerFloodErrorText(PeerFloodType type) {
|
QString PeerFloodErrorText(PeerFloodType type) {
|
||||||
auto link = textcmdLink(CreateInternalLinkHttps(qsl("spambot")), lang(lng_cant_more_info));
|
auto link = textcmdLink(CreateInternalLinkHttps(qsl("spambot")), lang(lng_cant_more_info));
|
||||||
|
@ -623,7 +624,7 @@ ContactsBox::Inner::Inner(QWidget *parent, UserData *bot) : TWidget(parent)
|
||||||
}
|
}
|
||||||
|
|
||||||
void ContactsBox::Inner::init() {
|
void ContactsBox::Inner::init() {
|
||||||
subscribe(FileDownload::ImageLoaded(), [this] { update(); });
|
subscribe(AuthSession::CurrentDownloaderTaskFinished(), [this] { update(); });
|
||||||
connect(_addContactLnk, SIGNAL(clicked()), App::wnd(), SLOT(onShowAddContact()));
|
connect(_addContactLnk, SIGNAL(clicked()), App::wnd(), SLOT(onShowAddContact()));
|
||||||
connect(_allAdmins, SIGNAL(changed()), this, SLOT(onAllAdminsChanged()));
|
connect(_allAdmins, SIGNAL(changed()), this, SLOT(onAllAdminsChanged()));
|
||||||
|
|
||||||
|
@ -848,7 +849,7 @@ void ContactsBox::Inner::loadProfilePhotos() {
|
||||||
|
|
||||||
auto yFrom = _visibleTop - _rowsTop;
|
auto yFrom = _visibleTop - _rowsTop;
|
||||||
auto yTo = yFrom + (_visibleBottom - _visibleTop) * 5;
|
auto yTo = yFrom + (_visibleBottom - _visibleTop) * 5;
|
||||||
MTP::clearLoaderPriorities();
|
AuthSession::Current().downloader()->clearPriorities();
|
||||||
|
|
||||||
if (yTo < 0) return;
|
if (yTo < 0) return;
|
||||||
if (yFrom < 0) yFrom = 0;
|
if (yFrom < 0) yFrom = 0;
|
||||||
|
|
|
@ -25,6 +25,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||||
#include "storage/localstorage.h"
|
#include "storage/localstorage.h"
|
||||||
#include "lang.h"
|
#include "lang.h"
|
||||||
#include "mainwindow.h"
|
#include "mainwindow.h"
|
||||||
|
#include "auth_session.h"
|
||||||
|
|
||||||
LocalStorageBox::LocalStorageBox(QWidget *parent)
|
LocalStorageBox::LocalStorageBox(QWidget *parent)
|
||||||
: _clear(this, lang(lng_local_storage_clear), st::boxLinkButton) {
|
: _clear(this, lang(lng_local_storage_clear), st::boxLinkButton) {
|
||||||
|
@ -40,7 +41,7 @@ void LocalStorageBox::prepare() {
|
||||||
connect(App::wnd(), SIGNAL(tempDirCleared(int)), this, SLOT(onTempDirCleared(int)));
|
connect(App::wnd(), SIGNAL(tempDirCleared(int)), this, SLOT(onTempDirCleared(int)));
|
||||||
connect(App::wnd(), SIGNAL(tempDirClearFailed(int)), this, SLOT(onTempDirClearFailed(int)));
|
connect(App::wnd(), SIGNAL(tempDirClearFailed(int)), this, SLOT(onTempDirClearFailed(int)));
|
||||||
|
|
||||||
subscribe(FileDownload::ImageLoaded(), [this] { update(); });
|
subscribe(AuthSession::CurrentDownloaderTaskFinished(), [this] { update(); });
|
||||||
|
|
||||||
updateControls();
|
updateControls();
|
||||||
|
|
||||||
|
|
|
@ -31,7 +31,8 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||||
#include "ui/widgets/scroll_area.h"
|
#include "ui/widgets/scroll_area.h"
|
||||||
#include "ui/effects/ripple_animation.h"
|
#include "ui/effects/ripple_animation.h"
|
||||||
#include "observer_peer.h"
|
#include "observer_peer.h"
|
||||||
|
#include "auth_session.h"
|
||||||
|
#include "storage/file_download.h"
|
||||||
|
|
||||||
MembersAddButton::MembersAddButton(QWidget *parent, const style::TwoIconButton &st) : RippleButton(parent, st.ripple)
|
MembersAddButton::MembersAddButton(QWidget *parent, const style::TwoIconButton &st) : RippleButton(parent, st.ripple)
|
||||||
, _st(st) {
|
, _st(st) {
|
||||||
|
@ -132,7 +133,7 @@ MembersBox::Inner::Inner(QWidget *parent, ChannelData *channel, MembersFilter fi
|
||||||
, _kickWidth(st::normalFont->width(_kickText))
|
, _kickWidth(st::normalFont->width(_kickText))
|
||||||
, _aboutWidth(st::boxWideWidth - st::contactsPadding.left() - st::contactsPadding.right())
|
, _aboutWidth(st::boxWideWidth - st::contactsPadding.left() - st::contactsPadding.right())
|
||||||
, _about(_aboutWidth) {
|
, _about(_aboutWidth) {
|
||||||
subscribe(FileDownload::ImageLoaded(), [this] { update(); });
|
subscribe(AuthSession::CurrentDownloaderTaskFinished(), [this] { update(); });
|
||||||
|
|
||||||
connect(App::main(), SIGNAL(peerNameChanged(PeerData*,const PeerData::Names&,const PeerData::NameFirstChars&)), this, SLOT(onPeerNameChanged(PeerData*, const PeerData::Names&, const PeerData::NameFirstChars&)));
|
connect(App::main(), SIGNAL(peerNameChanged(PeerData*,const PeerData::Names&,const PeerData::NameFirstChars&)), this, SLOT(onPeerNameChanged(PeerData*, const PeerData::Names&, const PeerData::NameFirstChars&)));
|
||||||
connect(App::main(), SIGNAL(peerPhotoChanged(PeerData*)), this, SLOT(peerUpdated(PeerData*)));
|
connect(App::main(), SIGNAL(peerPhotoChanged(PeerData*)), this, SLOT(peerUpdated(PeerData*)));
|
||||||
|
@ -341,7 +342,7 @@ void MembersBox::Inner::loadProfilePhotos() {
|
||||||
|
|
||||||
auto yFrom = _visibleTop;
|
auto yFrom = _visibleTop;
|
||||||
auto yTo = yFrom + (_visibleBottom - _visibleTop) * 5;
|
auto yTo = yFrom + (_visibleBottom - _visibleTop) * 5;
|
||||||
MTP::clearLoaderPriorities();
|
AuthSession::Current().downloader()->clearPriorities();
|
||||||
|
|
||||||
if (yTo < 0) return;
|
if (yTo < 0) return;
|
||||||
if (yFrom < 0) yFrom = 0;
|
if (yFrom < 0) yFrom = 0;
|
||||||
|
|
|
@ -28,11 +28,15 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||||
#include "styles/style_window.h"
|
#include "styles/style_window.h"
|
||||||
#include "mainwindow.h"
|
#include "mainwindow.h"
|
||||||
#include "storage/localstorage.h"
|
#include "storage/localstorage.h"
|
||||||
|
#include "auth_session.h"
|
||||||
|
#include "window/notifications_manager.h"
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
constexpr int kMaxNotificationsCount = 5;
|
constexpr int kMaxNotificationsCount = 5;
|
||||||
|
|
||||||
|
using ChangeType = Window::Notifications::ChangeType;
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
class NotificationsBox::SampleWidget : public QWidget {
|
class NotificationsBox::SampleWidget : public QWidget {
|
||||||
|
@ -190,7 +194,7 @@ void NotificationsBox::countChanged() {
|
||||||
|
|
||||||
if (currentCount() != Global::NotificationsCount()) {
|
if (currentCount() != Global::NotificationsCount()) {
|
||||||
Global::SetNotificationsCount(currentCount());
|
Global::SetNotificationsCount(currentCount());
|
||||||
Global::RefNotifySettingsChanged().notify(Notify::ChangeType::MaxCount);
|
AuthSession::Current().notifications()->settingsChanged().notify(ChangeType::MaxCount);
|
||||||
Local::writeUserSettings();
|
Local::writeUserSettings();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -347,7 +351,7 @@ void NotificationsBox::setOverCorner(Notify::ScreenCorner corner) {
|
||||||
_isOverCorner = true;
|
_isOverCorner = true;
|
||||||
setCursor(style::cur_pointer);
|
setCursor(style::cur_pointer);
|
||||||
Global::SetNotificationsDemoIsShown(true);
|
Global::SetNotificationsDemoIsShown(true);
|
||||||
Global::RefNotifySettingsChanged().notify(Notify::ChangeType::DemoIsShown);
|
AuthSession::Current().notifications()->settingsChanged().notify(ChangeType::DemoIsShown);
|
||||||
}
|
}
|
||||||
_overCorner = corner;
|
_overCorner = corner;
|
||||||
|
|
||||||
|
@ -382,7 +386,7 @@ void NotificationsBox::clearOverCorner() {
|
||||||
_isOverCorner = false;
|
_isOverCorner = false;
|
||||||
setCursor(style::cur_default);
|
setCursor(style::cur_default);
|
||||||
Global::SetNotificationsDemoIsShown(false);
|
Global::SetNotificationsDemoIsShown(false);
|
||||||
Global::RefNotifySettingsChanged().notify(Notify::ChangeType::DemoIsShown);
|
AuthSession::Current().notifications()->settingsChanged().notify(ChangeType::DemoIsShown);
|
||||||
|
|
||||||
for_const (auto &samples, _cornerSamples) {
|
for_const (auto &samples, _cornerSamples) {
|
||||||
for_const (auto widget, samples) {
|
for_const (auto widget, samples) {
|
||||||
|
@ -409,7 +413,7 @@ void NotificationsBox::mouseReleaseEvent(QMouseEvent *e) {
|
||||||
|
|
||||||
if (_chosenCorner != Global::NotificationsCorner()) {
|
if (_chosenCorner != Global::NotificationsCorner()) {
|
||||||
Global::SetNotificationsCorner(_chosenCorner);
|
Global::SetNotificationsCorner(_chosenCorner);
|
||||||
Global::RefNotifySettingsChanged().notify(Notify::ChangeType::Corner);
|
AuthSession::Current().notifications()->settingsChanged().notify(ChangeType::Corner);
|
||||||
Local::writeUserSettings();
|
Local::writeUserSettings();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -294,7 +294,7 @@ ShareBox::Inner::Inner(QWidget *parent, ShareBox::FilterCallback &&filterCallbac
|
||||||
subscribe(Notify::PeerUpdated(), Notify::PeerUpdatedHandler(observeEvents, [this](const Notify::PeerUpdate &update) {
|
subscribe(Notify::PeerUpdated(), Notify::PeerUpdatedHandler(observeEvents, [this](const Notify::PeerUpdate &update) {
|
||||||
notifyPeerUpdated(update);
|
notifyPeerUpdated(update);
|
||||||
}));
|
}));
|
||||||
subscribe(FileDownload::ImageLoaded(), [this] { update(); });
|
subscribe(AuthSession::CurrentDownloaderTaskFinished(), [this] { update(); });
|
||||||
|
|
||||||
subscribe(Window::Theme::Background(), [this](const Window::Theme::BackgroundUpdate &update) {
|
subscribe(Window::Theme::Background(), [this](const Window::Theme::BackgroundUpdate &update) {
|
||||||
if (update.paletteChanged()) {
|
if (update.paletteChanged()) {
|
||||||
|
@ -435,7 +435,7 @@ void ShareBox::Inner::loadProfilePhotos(int yFrom) {
|
||||||
yFrom *= _columnCount;
|
yFrom *= _columnCount;
|
||||||
yTo *= _columnCount;
|
yTo *= _columnCount;
|
||||||
|
|
||||||
MTP::clearLoaderPriorities();
|
AuthSession::Current().downloader()->clearPriorities();
|
||||||
if (_filter.isEmpty()) {
|
if (_filter.isEmpty()) {
|
||||||
if (!_chatsIndexed->isEmpty()) {
|
if (!_chatsIndexed->isEmpty()) {
|
||||||
auto i = _chatsIndexed->cfind(yFrom, _rowHeight);
|
auto i = _chatsIndexed->cfind(yFrom, _rowHeight);
|
||||||
|
@ -953,7 +953,7 @@ void shareGameScoreByHash(const QString &hash) {
|
||||||
}
|
}
|
||||||
|
|
||||||
auto hashDataInts = reinterpret_cast<int32*>(hashData.data());
|
auto hashDataInts = reinterpret_cast<int32*>(hashData.data());
|
||||||
if (hashDataInts[0] != AuthSession::CurrentUserId()) {
|
if (!AuthSession::Exists() || hashDataInts[0] != AuthSession::CurrentUserId()) {
|
||||||
Ui::show(Box<InformBox>(lang(lng_share_wrong_user)));
|
Ui::show(Box<InformBox>(lang(lng_share_wrong_user)));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,6 +35,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||||
#include "ui/effects/ripple_animation.h"
|
#include "ui/effects/ripple_animation.h"
|
||||||
#include "ui/effects/slide_animation.h"
|
#include "ui/effects/slide_animation.h"
|
||||||
#include "ui/widgets/discrete_sliders.h"
|
#include "ui/widgets/discrete_sliders.h"
|
||||||
|
#include "auth_session.h"
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
|
@ -576,7 +577,7 @@ StickersBox::Inner::Inner(QWidget *parent, const Stickers::Order &archivedIds) :
|
||||||
}
|
}
|
||||||
|
|
||||||
void StickersBox::Inner::setup() {
|
void StickersBox::Inner::setup() {
|
||||||
subscribe(FileDownload::ImageLoaded(), [this] {
|
subscribe(AuthSession::CurrentDownloaderTaskFinished(), [this] {
|
||||||
update();
|
update();
|
||||||
readVisibleSets();
|
readVisibleSets();
|
||||||
});
|
});
|
||||||
|
|
|
@ -32,6 +32,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||||
#include "styles/style_stickers.h"
|
#include "styles/style_stickers.h"
|
||||||
#include "ui/widgets/buttons.h"
|
#include "ui/widgets/buttons.h"
|
||||||
#include "ui/widgets/scroll_area.h"
|
#include "ui/widgets/scroll_area.h"
|
||||||
|
#include "auth_session.h"
|
||||||
|
|
||||||
StickerSetBox::StickerSetBox(QWidget*, const MTPInputStickerSet &set)
|
StickerSetBox::StickerSetBox(QWidget*, const MTPInputStickerSet &set)
|
||||||
: _set(set) {
|
: _set(set) {
|
||||||
|
@ -109,7 +110,7 @@ StickerSetBox::Inner::Inner(QWidget *parent, const MTPInputStickerSet &set) : TW
|
||||||
MTP::send(MTPmessages_GetStickerSet(_input), rpcDone(&Inner::gotSet), rpcFail(&Inner::failedSet));
|
MTP::send(MTPmessages_GetStickerSet(_input), rpcDone(&Inner::gotSet), rpcFail(&Inner::failedSet));
|
||||||
App::main()->updateStickers();
|
App::main()->updateStickers();
|
||||||
|
|
||||||
subscribe(FileDownload::ImageLoaded(), [this] { update(); });
|
subscribe(AuthSession::CurrentDownloaderTaskFinished(), [this] { update(); });
|
||||||
|
|
||||||
setMouseTracking(true);
|
setMouseTracking(true);
|
||||||
|
|
||||||
|
|
|
@ -176,7 +176,7 @@ struct vtable_once_impl<Lambda, false, Return, Args...> : public vtable_base<Ret
|
||||||
vtable_once_impl() : Parent(
|
vtable_once_impl() : Parent(
|
||||||
&bad_construct_copy,
|
&bad_construct_copy,
|
||||||
&vtable_once_impl::construct_move_other_method,
|
&vtable_once_impl::construct_move_other_method,
|
||||||
&bad_const_call<Args...>,
|
&bad_const_call<Return, Args...>,
|
||||||
&vtable_once_impl::call_method,
|
&vtable_once_impl::call_method,
|
||||||
&vtable_once_impl::destruct_method) {
|
&vtable_once_impl::destruct_method) {
|
||||||
}
|
}
|
||||||
|
|
|
@ -376,7 +376,7 @@ public:
|
||||||
|
|
||||||
void setForced(parameter_type<Type> newValue, bool sync = false) {
|
void setForced(parameter_type<Type> newValue, bool sync = false) {
|
||||||
_value = newValue;
|
_value = newValue;
|
||||||
_observable.notify(_value, sync);
|
changed().notify(_value, sync);
|
||||||
}
|
}
|
||||||
|
|
||||||
void set(parameter_type<Type> newValue, bool sync = false) {
|
void set(parameter_type<Type> newValue, bool sync = false) {
|
||||||
|
@ -388,16 +388,16 @@ public:
|
||||||
template <typename Callback>
|
template <typename Callback>
|
||||||
void process(Callback callback, bool sync = false) {
|
void process(Callback callback, bool sync = false) {
|
||||||
callback(_value);
|
callback(_value);
|
||||||
_observable.notify(_value, sync);
|
changed().notify(_value, sync);
|
||||||
}
|
}
|
||||||
|
|
||||||
Observable<Type> &observable() {
|
Observable<Type> &changed() {
|
||||||
return _observable;
|
return _changed;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Type _value;
|
Type _value;
|
||||||
Observable<Type> _observable;
|
Observable<Type> _changed;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -416,12 +416,12 @@ protected:
|
||||||
|
|
||||||
template <typename Type, typename Lambda>
|
template <typename Type, typename Lambda>
|
||||||
int subscribe(base::Variable<Type> &variable, Lambda &&handler) {
|
int subscribe(base::Variable<Type> &variable, Lambda &&handler) {
|
||||||
return subscribe(variable.observable(), std::forward<Lambda>(handler));
|
return subscribe(variable.changed(), std::forward<Lambda>(handler));
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Type, typename Lambda>
|
template <typename Type, typename Lambda>
|
||||||
int subscribe(base::Variable<Type> *variable, Lambda &&handler) {
|
int subscribe(base::Variable<Type> *variable, Lambda &&handler) {
|
||||||
return subscribe(variable->observable(), std::forward<Lambda>(handler));
|
return subscribe(variable->changed(), std::forward<Lambda>(handler));
|
||||||
}
|
}
|
||||||
|
|
||||||
void unsubscribe(int index) {
|
void unsubscribe(int index) {
|
||||||
|
|
|
@ -20,30 +20,14 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||||
*/
|
*/
|
||||||
#include "core/task_queue.h"
|
#include "core/task_queue.h"
|
||||||
|
|
||||||
|
#include <thread>
|
||||||
|
#include <condition_variable>
|
||||||
|
|
||||||
namespace base {
|
namespace base {
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
auto MainThreadId = QThread::currentThreadId();
|
auto MainThreadId = std::this_thread::get_id();
|
||||||
const auto MaxThreadsCount = qMax(QThread::idealThreadCount(), 2);
|
const auto MaxThreadsCount = qMax(std::thread::hardware_concurrency(), 2U);
|
||||||
|
|
||||||
template <typename Lambda>
|
|
||||||
class Thread : public QThread {
|
|
||||||
public:
|
|
||||||
Thread(Lambda code) : _code(std::move(code)) {
|
|
||||||
}
|
|
||||||
void run() override {
|
|
||||||
_code();
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
Lambda _code;
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename Lambda>
|
|
||||||
object_ptr<Thread<Lambda>> MakeThread(Lambda code) {
|
|
||||||
return object_ptr<Thread<Lambda>>(std::move(code));
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
|
@ -76,7 +60,7 @@ class TaskQueue::TaskThreadPool {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
TaskThreadPool(const Private &) { }
|
TaskThreadPool(const Private &) { }
|
||||||
static const QSharedPointer<TaskThreadPool> &Instance();
|
static const std::shared_ptr<TaskThreadPool> &Instance();
|
||||||
|
|
||||||
void AddQueueTask(TaskQueue *queue, Task &&task);
|
void AddQueueTask(TaskQueue *queue, Task &&task);
|
||||||
void RemoveQueue(TaskQueue *queue);
|
void RemoveQueue(TaskQueue *queue);
|
||||||
|
@ -84,16 +68,15 @@ public:
|
||||||
~TaskThreadPool();
|
~TaskThreadPool();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
void ThreadFunction();
|
void ThreadFunction();
|
||||||
|
|
||||||
std::vector<object_ptr<QThread>> threads_;
|
std::vector<std::thread> threads_;
|
||||||
QMutex queues_mutex_;
|
std::mutex queues_mutex_;
|
||||||
|
|
||||||
// queues_mutex_ must be locked when working with the list.
|
// queues_mutex_ must be locked when working with the list.
|
||||||
TaskQueueList queue_list_;
|
TaskQueueList queue_list_;
|
||||||
|
|
||||||
QWaitCondition thread_condition_;
|
std::condition_variable thread_condition_;
|
||||||
bool stopped_ = false;
|
bool stopped_ = false;
|
||||||
int tasks_in_process_ = 0;
|
int tasks_in_process_ = 0;
|
||||||
int background_tasks_in_process_ = 0;
|
int background_tasks_in_process_ = 0;
|
||||||
|
@ -192,7 +175,7 @@ TaskQueue *TaskQueue::TaskQueueList::TakeFirst(int list_index_) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void TaskQueue::TaskThreadPool::AddQueueTask(TaskQueue *queue, Task &&task) {
|
void TaskQueue::TaskThreadPool::AddQueueTask(TaskQueue *queue, Task &&task) {
|
||||||
QMutexLocker lock(&queues_mutex_);
|
std::unique_lock<std::mutex> lock(queues_mutex_);
|
||||||
|
|
||||||
queue->tasks_.push_back(std::move(task));
|
queue->tasks_.push_back(std::move(task));
|
||||||
auto list_was_empty = queue_list_.Empty(kAllQueuesList);
|
auto list_was_empty = queue_list_.Empty(kAllQueuesList);
|
||||||
|
@ -207,18 +190,17 @@ void TaskQueue::TaskThreadPool::AddQueueTask(TaskQueue *queue, Task &&task) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (will_create_thread) {
|
if (will_create_thread) {
|
||||||
threads_.push_back(MakeThread([this]() {
|
threads_.emplace_back([this]() {
|
||||||
ThreadFunction();
|
ThreadFunction();
|
||||||
}));
|
});
|
||||||
threads_.back()->start();
|
|
||||||
} else if (some_threads_are_vacant) {
|
} else if (some_threads_are_vacant) {
|
||||||
t_assert(threads_count > tasks_in_process_);
|
t_assert(threads_count > tasks_in_process_);
|
||||||
thread_condition_.wakeOne();
|
thread_condition_.notify_one();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void TaskQueue::TaskThreadPool::RemoveQueue(TaskQueue *queue) {
|
void TaskQueue::TaskThreadPool::RemoveQueue(TaskQueue *queue) {
|
||||||
QMutexLocker lock(&queues_mutex_);
|
std::unique_lock<std::mutex> lock(queues_mutex_);
|
||||||
if (queue_list_.IsInList(queue)) {
|
if (queue_list_.IsInList(queue)) {
|
||||||
queue_list_.Unregister(queue);
|
queue_list_.Unregister(queue);
|
||||||
}
|
}
|
||||||
|
@ -229,18 +211,18 @@ void TaskQueue::TaskThreadPool::RemoveQueue(TaskQueue *queue) {
|
||||||
|
|
||||||
TaskQueue::TaskThreadPool::~TaskThreadPool() {
|
TaskQueue::TaskThreadPool::~TaskThreadPool() {
|
||||||
{
|
{
|
||||||
QMutexLocker lock(&queues_mutex_);
|
std::unique_lock<std::mutex> lock(queues_mutex_);
|
||||||
queue_list_.Clear();
|
queue_list_.Clear();
|
||||||
stopped_ = true;
|
stopped_ = true;
|
||||||
}
|
}
|
||||||
thread_condition_.wakeAll();
|
thread_condition_.notify_all();
|
||||||
for (auto &thread : threads_) {
|
for (auto &thread : threads_) {
|
||||||
thread->wait();
|
thread.join();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const QSharedPointer<TaskQueue::TaskThreadPool> &TaskQueue::TaskThreadPool::Instance() { // static
|
const std::shared_ptr<TaskQueue::TaskThreadPool> &TaskQueue::TaskThreadPool::Instance() { // static
|
||||||
static auto Pool = MakeShared<TaskThreadPool>(Private());
|
static auto Pool = std::make_shared<TaskThreadPool>(Private());
|
||||||
return Pool;
|
return Pool;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -259,7 +241,7 @@ void TaskQueue::TaskThreadPool::ThreadFunction() {
|
||||||
while (true) {
|
while (true) {
|
||||||
Task task;
|
Task task;
|
||||||
{
|
{
|
||||||
QMutexLocker lock(&queues_mutex_);
|
std::unique_lock<std::mutex> lock(queues_mutex_);
|
||||||
|
|
||||||
// Finish the previous task processing.
|
// Finish the previous task processing.
|
||||||
if (task_was_processed) {
|
if (task_was_processed) {
|
||||||
|
@ -285,7 +267,7 @@ void TaskQueue::TaskThreadPool::ThreadFunction() {
|
||||||
if (stopped_) {
|
if (stopped_) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
thread_condition_.wait(&queues_mutex_);
|
thread_condition_.wait(lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Select a task we will be processing.
|
// Select a task we will be processing.
|
||||||
|
@ -331,7 +313,7 @@ TaskQueue::TaskQueue(Type type, Priority priority)
|
||||||
|
|
||||||
TaskQueue::~TaskQueue() {
|
TaskQueue::~TaskQueue() {
|
||||||
if (type_ != Type::Main && type_ != Type::Special) {
|
if (type_ != Type::Main && type_ != Type::Special) {
|
||||||
if (auto thread_pool = weak_thread_pool_.toStrongRef()) {
|
if (auto thread_pool = weak_thread_pool_.lock()) {
|
||||||
thread_pool->RemoveQueue(this);
|
thread_pool->RemoveQueue(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -339,7 +321,7 @@ TaskQueue::~TaskQueue() {
|
||||||
|
|
||||||
void TaskQueue::Put(Task &&task) {
|
void TaskQueue::Put(Task &&task) {
|
||||||
if (type_ == Type::Main) {
|
if (type_ == Type::Main) {
|
||||||
QMutexLocker lock(&tasks_mutex_);
|
std::unique_lock<std::mutex> lock(tasks_mutex_);
|
||||||
tasks_.push_back(std::move(task));
|
tasks_.push_back(std::move(task));
|
||||||
|
|
||||||
Sandbox::MainThreadTaskAdded();
|
Sandbox::MainThreadTaskAdded();
|
||||||
|
@ -350,14 +332,14 @@ void TaskQueue::Put(Task &&task) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void TaskQueue::ProcessMainTasks() { // static
|
void TaskQueue::ProcessMainTasks() { // static
|
||||||
t_assert(QThread::currentThreadId() == MainThreadId);
|
t_assert(std::this_thread::get_id() == MainThreadId);
|
||||||
|
|
||||||
while (ProcessOneMainTask()) {
|
while (ProcessOneMainTask()) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void TaskQueue::ProcessMainTasks(TimeMs max_time_spent) { // static
|
void TaskQueue::ProcessMainTasks(TimeMs max_time_spent) { // static
|
||||||
t_assert(QThread::currentThreadId() == MainThreadId);
|
t_assert(std::this_thread::get_id() == MainThreadId);
|
||||||
|
|
||||||
auto start_time = getms();
|
auto start_time = getms();
|
||||||
while (ProcessOneMainTask()) {
|
while (ProcessOneMainTask()) {
|
||||||
|
@ -370,7 +352,7 @@ void TaskQueue::ProcessMainTasks(TimeMs max_time_spent) { // static
|
||||||
bool TaskQueue::ProcessOneMainTask() { // static
|
bool TaskQueue::ProcessOneMainTask() { // static
|
||||||
Task task;
|
Task task;
|
||||||
{
|
{
|
||||||
QMutexLocker lock(&Main().tasks_mutex_);
|
std::unique_lock<std::mutex> lock(Main().tasks_mutex_);
|
||||||
auto &tasks = Main().tasks_;
|
auto &tasks = Main().tasks_;
|
||||||
if (tasks.empty()) {
|
if (tasks.empty()) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -386,7 +368,7 @@ bool TaskQueue::ProcessOneMainTask() { // static
|
||||||
|
|
||||||
bool TaskQueue::IsMyThread() const {
|
bool TaskQueue::IsMyThread() const {
|
||||||
if (type_ == Type::Main) {
|
if (type_ == Type::Main) {
|
||||||
return (QThread::currentThreadId() == MainThreadId);
|
return (std::this_thread::get_id() == MainThreadId);
|
||||||
}
|
}
|
||||||
t_assert(type_ != Type::Special);
|
t_assert(type_ != Type::Special);
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -20,6 +20,9 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||||
*/
|
*/
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <mutex>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
namespace base {
|
namespace base {
|
||||||
|
|
||||||
using Task = lambda_once<void()>;
|
using Task = lambda_once<void()>;
|
||||||
|
@ -70,11 +73,11 @@ private:
|
||||||
const Priority priority_;
|
const Priority priority_;
|
||||||
|
|
||||||
std::deque<Task> tasks_;
|
std::deque<Task> tasks_;
|
||||||
QMutex tasks_mutex_; // Only for the main queue.
|
std::mutex tasks_mutex_; // Only for the main queue.
|
||||||
|
|
||||||
// Only for the other queues, not main.
|
// Only for the other queues, not main.
|
||||||
class TaskThreadPool;
|
class TaskThreadPool;
|
||||||
QWeakPointer<TaskThreadPool> weak_thread_pool_;
|
std::weak_ptr<TaskThreadPool> weak_thread_pool_;
|
||||||
|
|
||||||
class TaskQueueList;
|
class TaskQueueList;
|
||||||
|
|
||||||
|
|
|
@ -45,6 +45,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||||
#include "autoupdater.h"
|
#include "autoupdater.h"
|
||||||
#include "observer_peer.h"
|
#include "observer_peer.h"
|
||||||
#include "auth_session.h"
|
#include "auth_session.h"
|
||||||
|
#include "window/notifications_manager.h"
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
|
@ -95,7 +96,7 @@ DialogsInner::DialogsInner(QWidget *parent, QWidget *main) : SplittedWidget(pare
|
||||||
connect(_cancelSearchInPeer, SIGNAL(clicked()), this, SIGNAL(cancelSearchInPeer()));
|
connect(_cancelSearchInPeer, SIGNAL(clicked()), this, SIGNAL(cancelSearchInPeer()));
|
||||||
_cancelSearchInPeer->hide();
|
_cancelSearchInPeer->hide();
|
||||||
|
|
||||||
subscribe(FileDownload::ImageLoaded(), [this] { update(); });
|
subscribe(AuthSession::CurrentDownloaderTaskFinished(), [this] { update(); });
|
||||||
subscribe(Global::RefItemRemoved(), [this](HistoryItem *item) {
|
subscribe(Global::RefItemRemoved(), [this](HistoryItem *item) {
|
||||||
itemRemoved(item);
|
itemRemoved(item);
|
||||||
});
|
});
|
||||||
|
@ -999,7 +1000,7 @@ void DialogsInner::removeDialog(History *history) {
|
||||||
if (_dialogsImportant) {
|
if (_dialogsImportant) {
|
||||||
history->removeFromChatList(Dialogs::Mode::Important, _dialogsImportant.get());
|
history->removeFromChatList(Dialogs::Mode::Important, _dialogsImportant.get());
|
||||||
}
|
}
|
||||||
if (App::wnd()) App::wnd()->notifyClear(history);
|
AuthSession::Current().notifications()->clearFromHistory(history);
|
||||||
if (_contacts->contains(history->peer->id)) {
|
if (_contacts->contains(history->peer->id)) {
|
||||||
if (!_contactsNoDialogs->contains(history->peer->id)) {
|
if (!_contactsNoDialogs->contains(history->peer->id)) {
|
||||||
_contactsNoDialogs->addByName(history);
|
_contactsNoDialogs->addByName(history);
|
||||||
|
@ -1889,7 +1890,7 @@ void DialogsInner::loadPeerPhotos() {
|
||||||
|
|
||||||
auto yFrom = _visibleTop;
|
auto yFrom = _visibleTop;
|
||||||
auto yTo = _visibleTop + (_visibleBottom - _visibleTop) * (PreloadHeightsCount + 1);
|
auto yTo = _visibleTop + (_visibleBottom - _visibleTop) * (PreloadHeightsCount + 1);
|
||||||
MTP::clearLoaderPriorities();
|
AuthSession::Current().downloader()->clearPriorities();
|
||||||
if (_state == DefaultState) {
|
if (_state == DefaultState) {
|
||||||
auto otherStart = shownDialogs()->size() * st::dialogsRowHeight;
|
auto otherStart = shownDialogs()->size() * st::dialogsRowHeight;
|
||||||
if (yFrom < otherStart) {
|
if (yFrom < otherStart) {
|
||||||
|
|
|
@ -686,7 +686,6 @@ struct Data {
|
||||||
int NotificationsCount = 3;
|
int NotificationsCount = 3;
|
||||||
Notify::ScreenCorner NotificationsCorner = Notify::ScreenCorner::BottomRight;
|
Notify::ScreenCorner NotificationsCorner = Notify::ScreenCorner::BottomRight;
|
||||||
bool NotificationsDemoIsShown = false;
|
bool NotificationsDemoIsShown = false;
|
||||||
base::Observable<Notify::ChangeType> NotifySettingsChanged;
|
|
||||||
|
|
||||||
DBIConnectionType ConnectionType = dbictAuto;
|
DBIConnectionType ConnectionType = dbictAuto;
|
||||||
bool TryIPv6 = (cPlatform() == dbipWindows) ? false : true;
|
bool TryIPv6 = (cPlatform() == dbipWindows) ? false : true;
|
||||||
|
@ -699,6 +698,8 @@ struct Data {
|
||||||
bool LocalPasscode = false;
|
bool LocalPasscode = false;
|
||||||
base::Observable<void> LocalPasscodeChanged;
|
base::Observable<void> LocalPasscodeChanged;
|
||||||
|
|
||||||
|
base::Variable<DBIWorkMode> WorkMode = { dbiwmWindowAndTray };
|
||||||
|
|
||||||
base::Observable<HistoryItem*> ItemRemoved;
|
base::Observable<HistoryItem*> ItemRemoved;
|
||||||
base::Observable<void> UnreadCounterUpdate;
|
base::Observable<void> UnreadCounterUpdate;
|
||||||
base::Observable<void> PeerChooseCancel;
|
base::Observable<void> PeerChooseCancel;
|
||||||
|
@ -807,7 +808,6 @@ DefineVar(Global, bool, NativeNotifications);
|
||||||
DefineVar(Global, int, NotificationsCount);
|
DefineVar(Global, int, NotificationsCount);
|
||||||
DefineVar(Global, Notify::ScreenCorner, NotificationsCorner);
|
DefineVar(Global, Notify::ScreenCorner, NotificationsCorner);
|
||||||
DefineVar(Global, bool, NotificationsDemoIsShown);
|
DefineVar(Global, bool, NotificationsDemoIsShown);
|
||||||
DefineRefVar(Global, base::Observable<Notify::ChangeType>, NotifySettingsChanged);
|
|
||||||
|
|
||||||
DefineVar(Global, DBIConnectionType, ConnectionType);
|
DefineVar(Global, DBIConnectionType, ConnectionType);
|
||||||
DefineVar(Global, bool, TryIPv6);
|
DefineVar(Global, bool, TryIPv6);
|
||||||
|
@ -820,6 +820,8 @@ DefineVar(Global, int, AutoLock);
|
||||||
DefineVar(Global, bool, LocalPasscode);
|
DefineVar(Global, bool, LocalPasscode);
|
||||||
DefineRefVar(Global, base::Observable<void>, LocalPasscodeChanged);
|
DefineRefVar(Global, base::Observable<void>, LocalPasscodeChanged);
|
||||||
|
|
||||||
|
DefineRefVar(Global, base::Variable<DBIWorkMode>, WorkMode);
|
||||||
|
|
||||||
DefineRefVar(Global, base::Observable<HistoryItem*>, ItemRemoved);
|
DefineRefVar(Global, base::Observable<HistoryItem*>, ItemRemoved);
|
||||||
DefineRefVar(Global, base::Observable<void>, UnreadCounterUpdate);
|
DefineRefVar(Global, base::Observable<void>, UnreadCounterUpdate);
|
||||||
DefineRefVar(Global, base::Observable<void>, PeerChooseCancel);
|
DefineRefVar(Global, base::Observable<void>, PeerChooseCancel);
|
||||||
|
|
|
@ -187,15 +187,6 @@ void historyMuteUpdated(History *history);
|
||||||
void handlePendingHistoryUpdate();
|
void handlePendingHistoryUpdate();
|
||||||
void unreadCounterUpdated();
|
void unreadCounterUpdated();
|
||||||
|
|
||||||
enum class ChangeType {
|
|
||||||
SoundEnabled,
|
|
||||||
IncludeMuted,
|
|
||||||
DesktopEnabled,
|
|
||||||
ViewParams,
|
|
||||||
MaxCount,
|
|
||||||
Corner,
|
|
||||||
DemoIsShown,
|
|
||||||
};
|
|
||||||
|
|
||||||
enum class ScreenCorner {
|
enum class ScreenCorner {
|
||||||
TopLeft = 0,
|
TopLeft = 0,
|
||||||
|
@ -214,14 +205,6 @@ inline bool IsTopCorner(ScreenCorner corner) {
|
||||||
|
|
||||||
} // namespace Notify
|
} // namespace Notify
|
||||||
|
|
||||||
namespace base {
|
|
||||||
|
|
||||||
template <>
|
|
||||||
struct custom_is_fast_copy_type<Notify::ChangeType> : public std::true_type {
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace base
|
|
||||||
|
|
||||||
#define DeclareReadOnlyVar(Type, Name) const Type &Name();
|
#define DeclareReadOnlyVar(Type, Name) const Type &Name();
|
||||||
#define DeclareRefVar(Type, Name) DeclareReadOnlyVar(Type, Name) \
|
#define DeclareRefVar(Type, Name) DeclareReadOnlyVar(Type, Name) \
|
||||||
Type &Ref##Name();
|
Type &Ref##Name();
|
||||||
|
@ -395,7 +378,6 @@ DeclareVar(bool, NativeNotifications);
|
||||||
DeclareVar(int, NotificationsCount);
|
DeclareVar(int, NotificationsCount);
|
||||||
DeclareVar(Notify::ScreenCorner, NotificationsCorner);
|
DeclareVar(Notify::ScreenCorner, NotificationsCorner);
|
||||||
DeclareVar(bool, NotificationsDemoIsShown);
|
DeclareVar(bool, NotificationsDemoIsShown);
|
||||||
DeclareRefVar(base::Observable<Notify::ChangeType>, NotifySettingsChanged);
|
|
||||||
|
|
||||||
DeclareVar(DBIConnectionType, ConnectionType);
|
DeclareVar(DBIConnectionType, ConnectionType);
|
||||||
DeclareVar(bool, TryIPv6);
|
DeclareVar(bool, TryIPv6);
|
||||||
|
@ -408,6 +390,8 @@ DeclareVar(int, AutoLock);
|
||||||
DeclareVar(bool, LocalPasscode);
|
DeclareVar(bool, LocalPasscode);
|
||||||
DeclareRefVar(base::Observable<void>, LocalPasscodeChanged);
|
DeclareRefVar(base::Observable<void>, LocalPasscodeChanged);
|
||||||
|
|
||||||
|
DeclareRefVar(base::Variable<DBIWorkMode>, WorkMode);
|
||||||
|
|
||||||
DeclareRefVar(base::Observable<HistoryItem*>, ItemRemoved);
|
DeclareRefVar(base::Observable<HistoryItem*>, ItemRemoved);
|
||||||
DeclareRefVar(base::Observable<void>, UnreadCounterUpdate);
|
DeclareRefVar(base::Observable<void>, UnreadCounterUpdate);
|
||||||
DeclareRefVar(base::Observable<void>, PeerChooseCancel);
|
DeclareRefVar(base::Observable<void>, PeerChooseCancel);
|
||||||
|
|
|
@ -32,6 +32,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||||
#include "window/top_bar_widget.h"
|
#include "window/top_bar_widget.h"
|
||||||
#include "observer_peer.h"
|
#include "observer_peer.h"
|
||||||
#include "auth_session.h"
|
#include "auth_session.h"
|
||||||
|
#include "window/notifications_manager.h"
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
|
@ -1503,7 +1504,7 @@ MsgId History::inboxRead(MsgId upTo) {
|
||||||
}
|
}
|
||||||
|
|
||||||
showFrom = nullptr;
|
showFrom = nullptr;
|
||||||
App::wnd()->notifyClear(this);
|
AuthSession::Current().notifications()->clearFromHistory(this);
|
||||||
|
|
||||||
return upTo;
|
return upTo;
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,6 +23,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||||
#include "structs.h"
|
#include "structs.h"
|
||||||
#include "dialogs/dialogs_common.h"
|
#include "dialogs/dialogs_common.h"
|
||||||
#include "ui/effects/send_action_animations.h"
|
#include "ui/effects/send_action_animations.h"
|
||||||
|
#include "core/observer.h"
|
||||||
|
|
||||||
void historyInit();
|
void historyInit();
|
||||||
|
|
||||||
|
|
|
@ -27,6 +27,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||||
#include "styles/style_history.h"
|
#include "styles/style_history.h"
|
||||||
#include "styles/style_widgets.h"
|
#include "styles/style_widgets.h"
|
||||||
#include "styles/style_stickers.h"
|
#include "styles/style_stickers.h"
|
||||||
|
#include "auth_session.h"
|
||||||
|
|
||||||
FieldAutocomplete::FieldAutocomplete(QWidget *parent) : TWidget(parent)
|
FieldAutocomplete::FieldAutocomplete(QWidget *parent) : TWidget(parent)
|
||||||
, _scroll(this, st::mentionScroll) {
|
, _scroll(this, st::mentionScroll) {
|
||||||
|
@ -533,7 +534,7 @@ FieldAutocompleteInner::FieldAutocompleteInner(FieldAutocomplete *parent, Mentio
|
||||||
, _previewShown(false) {
|
, _previewShown(false) {
|
||||||
_previewTimer.setSingleShot(true);
|
_previewTimer.setSingleShot(true);
|
||||||
connect(&_previewTimer, SIGNAL(timeout()), this, SLOT(onPreview()));
|
connect(&_previewTimer, SIGNAL(timeout()), this, SLOT(onPreview()));
|
||||||
subscribe(FileDownload::ImageLoaded(), [this] { update(); });
|
subscribe(AuthSession::CurrentDownloaderTaskFinished(), [this] { update(); });
|
||||||
}
|
}
|
||||||
|
|
||||||
void FieldAutocompleteInner::paintEvent(QPaintEvent *e) {
|
void FieldAutocompleteInner::paintEvent(QPaintEvent *e) {
|
||||||
|
|
|
@ -31,6 +31,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||||
#include "styles/style_dialogs.h"
|
#include "styles/style_dialogs.h"
|
||||||
#include "styles/style_widgets.h"
|
#include "styles/style_widgets.h"
|
||||||
#include "styles/style_history.h"
|
#include "styles/style_history.h"
|
||||||
|
#include "window/notifications_manager.h"
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
|
@ -2032,10 +2033,8 @@ bool HistoryService::updateDependent(bool force) {
|
||||||
}
|
}
|
||||||
updateDependentText();
|
updateDependentText();
|
||||||
}
|
}
|
||||||
if (force) {
|
if (force && gotDependencyItem) {
|
||||||
if (gotDependencyItem && App::wnd()) {
|
AuthSession::Current().notifications()->checkDelayed();
|
||||||
App::wnd()->notifySettingGot();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return (dependent->msg || !dependent->msgId);
|
return (dependent->msg || !dependent->msgId);
|
||||||
}
|
}
|
||||||
|
|
|
@ -61,6 +61,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||||
#include "ui/widgets/popup_menu.h"
|
#include "ui/widgets/popup_menu.h"
|
||||||
#include "platform/platform_file_utilities.h"
|
#include "platform/platform_file_utilities.h"
|
||||||
#include "auth_session.h"
|
#include "auth_session.h"
|
||||||
|
#include "window/notifications_manager.h"
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
|
@ -3130,7 +3131,7 @@ HistoryWidget::HistoryWidget(QWidget *parent) : TWidget(parent)
|
||||||
, _topShadow(this, st::shadowFg) {
|
, _topShadow(this, st::shadowFg) {
|
||||||
setAcceptDrops(true);
|
setAcceptDrops(true);
|
||||||
|
|
||||||
subscribe(FileDownload::ImageLoaded(), [this] { update(); });
|
subscribe(AuthSession::CurrentDownloaderTaskFinished(), [this] { update(); });
|
||||||
connect(_scroll, SIGNAL(scrolled()), this, SLOT(onScroll()));
|
connect(_scroll, SIGNAL(scrolled()), this, SLOT(onScroll()));
|
||||||
connect(_reportSpamPanel, SIGNAL(reportClicked()), this, SLOT(onReportSpamClicked()));
|
connect(_reportSpamPanel, SIGNAL(reportClicked()), this, SLOT(onReportSpamClicked()));
|
||||||
connect(_reportSpamPanel, SIGNAL(hideClicked()), this, SLOT(onReportSpamHide()));
|
connect(_reportSpamPanel, SIGNAL(hideClicked()), this, SLOT(onReportSpamHide()));
|
||||||
|
@ -4341,7 +4342,7 @@ void HistoryWidget::showHistory(const PeerId &peerId, MsgId showAtMsgId, bool re
|
||||||
if (_peer) {
|
if (_peer) {
|
||||||
App::forgetMedia();
|
App::forgetMedia();
|
||||||
_serviceImageCacheSize = imageCacheSize();
|
_serviceImageCacheSize = imageCacheSize();
|
||||||
MTP::clearLoaderPriorities();
|
AuthSession::Current().downloader()->clearPriorities();
|
||||||
|
|
||||||
_history = App::history(_peer->id);
|
_history = App::history(_peer->id);
|
||||||
_migrated = _peer->migrateFrom() ? App::history(_peer->migrateFrom()->id) : 0;
|
_migrated = _peer->migrateFrom() ? App::history(_peer->migrateFrom()->id) : 0;
|
||||||
|
@ -4797,7 +4798,7 @@ void HistoryWidget::newUnreadMsg(History *history, HistoryItem *item) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
App::wnd()->notifySchedule(history, item);
|
AuthSession::Current().notifications()->schedule(history, item);
|
||||||
history->setUnreadCount(history->unreadCount() + 1);
|
history->setUnreadCount(history->unreadCount() + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6803,8 +6804,6 @@ void HistoryWidget::sendFileConfirmed(const FileLoadResultPtr &file) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void HistoryWidget::onPhotoUploaded(const FullMsgId &newId, bool silent, const MTPInputFile &file) {
|
void HistoryWidget::onPhotoUploaded(const FullMsgId &newId, bool silent, const MTPInputFile &file) {
|
||||||
if (!AuthSession::Current()) return;
|
|
||||||
|
|
||||||
if (auto item = App::histItemById(newId)) {
|
if (auto item = App::histItemById(newId)) {
|
||||||
uint64 randomId = rand_value<uint64>();
|
uint64 randomId = rand_value<uint64>();
|
||||||
App::historyRegRandom(randomId, newId);
|
App::historyRegRandom(randomId, newId);
|
||||||
|
@ -6853,8 +6852,6 @@ namespace {
|
||||||
}
|
}
|
||||||
|
|
||||||
void HistoryWidget::onDocumentUploaded(const FullMsgId &newId, bool silent, const MTPInputFile &file) {
|
void HistoryWidget::onDocumentUploaded(const FullMsgId &newId, bool silent, const MTPInputFile &file) {
|
||||||
if (!AuthSession::Current()) return;
|
|
||||||
|
|
||||||
if (auto item = dynamic_cast<HistoryMessage*>(App::histItemById(newId))) {
|
if (auto item = dynamic_cast<HistoryMessage*>(App::histItemById(newId))) {
|
||||||
auto media = item->getMedia();
|
auto media = item->getMedia();
|
||||||
if (auto document = media ? media->getDocument() : nullptr) {
|
if (auto document = media ? media->getDocument() : nullptr) {
|
||||||
|
@ -6881,8 +6878,6 @@ void HistoryWidget::onDocumentUploaded(const FullMsgId &newId, bool silent, cons
|
||||||
}
|
}
|
||||||
|
|
||||||
void HistoryWidget::onThumbDocumentUploaded(const FullMsgId &newId, bool silent, const MTPInputFile &file, const MTPInputFile &thumb) {
|
void HistoryWidget::onThumbDocumentUploaded(const FullMsgId &newId, bool silent, const MTPInputFile &file, const MTPInputFile &thumb) {
|
||||||
if (!AuthSession::Current()) return;
|
|
||||||
|
|
||||||
if (auto item = dynamic_cast<HistoryMessage*>(App::histItemById(newId))) {
|
if (auto item = dynamic_cast<HistoryMessage*>(App::histItemById(newId))) {
|
||||||
auto media = item->getMedia();
|
auto media = item->getMedia();
|
||||||
if (auto document = media ? media->getDocument() : nullptr) {
|
if (auto document = media ? media->getDocument() : nullptr) {
|
||||||
|
@ -6909,8 +6904,6 @@ void HistoryWidget::onThumbDocumentUploaded(const FullMsgId &newId, bool silent,
|
||||||
}
|
}
|
||||||
|
|
||||||
void HistoryWidget::onPhotoProgress(const FullMsgId &newId) {
|
void HistoryWidget::onPhotoProgress(const FullMsgId &newId) {
|
||||||
if (!AuthSession::Current()) return;
|
|
||||||
|
|
||||||
if (auto item = App::histItemById(newId)) {
|
if (auto item = App::histItemById(newId)) {
|
||||||
auto photo = (item->getMedia() && item->getMedia()->type() == MediaTypePhoto) ? static_cast<HistoryPhoto*>(item->getMedia())->photo() : nullptr;
|
auto photo = (item->getMedia() && item->getMedia()->type() == MediaTypePhoto) ? static_cast<HistoryPhoto*>(item->getMedia())->photo() : nullptr;
|
||||||
if (!item->isPost()) {
|
if (!item->isPost()) {
|
||||||
|
@ -6921,8 +6914,6 @@ void HistoryWidget::onPhotoProgress(const FullMsgId &newId) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void HistoryWidget::onDocumentProgress(const FullMsgId &newId) {
|
void HistoryWidget::onDocumentProgress(const FullMsgId &newId) {
|
||||||
if (!AuthSession::Current()) return;
|
|
||||||
|
|
||||||
if (auto item = App::histItemById(newId)) {
|
if (auto item = App::histItemById(newId)) {
|
||||||
auto media = item->getMedia();
|
auto media = item->getMedia();
|
||||||
auto document = media ? media->getDocument() : nullptr;
|
auto document = media ? media->getDocument() : nullptr;
|
||||||
|
@ -6934,8 +6925,6 @@ void HistoryWidget::onDocumentProgress(const FullMsgId &newId) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void HistoryWidget::onPhotoFailed(const FullMsgId &newId) {
|
void HistoryWidget::onPhotoFailed(const FullMsgId &newId) {
|
||||||
if (!AuthSession::Current()) return;
|
|
||||||
|
|
||||||
HistoryItem *item = App::histItemById(newId);
|
HistoryItem *item = App::histItemById(newId);
|
||||||
if (item) {
|
if (item) {
|
||||||
if (!item->isPost()) {
|
if (!item->isPost()) {
|
||||||
|
@ -6946,8 +6935,6 @@ void HistoryWidget::onPhotoFailed(const FullMsgId &newId) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void HistoryWidget::onDocumentFailed(const FullMsgId &newId) {
|
void HistoryWidget::onDocumentFailed(const FullMsgId &newId) {
|
||||||
if (!AuthSession::Current()) return;
|
|
||||||
|
|
||||||
if (auto item = App::histItemById(newId)) {
|
if (auto item = App::histItemById(newId)) {
|
||||||
auto media = item->getMedia();
|
auto media = item->getMedia();
|
||||||
auto document = media ? media->getDocument() : nullptr;
|
auto document = media ? media->getDocument() : nullptr;
|
||||||
|
|
|
@ -425,6 +425,15 @@ QString Widget::Step::nextButtonText() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Widget::Step::finish(const MTPUser &user, QImage photo) {
|
void Widget::Step::finish(const MTPUser &user, QImage photo) {
|
||||||
|
if (user.type() != mtpc_user || !user.c_user().is_self()) {
|
||||||
|
// No idea what to do here.
|
||||||
|
// We could've reset intro and MTP, but this really should not happen.
|
||||||
|
Ui::show(Box<InformBox>("Internal error: bad user.is_self() after sign in."));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Messenger::Instance().authSessionCreate(user.c_user().vid.v);
|
||||||
|
|
||||||
App::wnd()->setupMain(&user);
|
App::wnd()->setupMain(&user);
|
||||||
|
|
||||||
// "this" is already deleted here by creating the main widget.
|
// "this" is already deleted here by creating the main widget.
|
||||||
|
|
|
@ -32,6 +32,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||||
#include "styles/style_stickers.h"
|
#include "styles/style_stickers.h"
|
||||||
#include "ui/widgets/shadow.h"
|
#include "ui/widgets/shadow.h"
|
||||||
#include "window/window_main_menu.h"
|
#include "window/window_main_menu.h"
|
||||||
|
#include "auth_session.h"
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
|
@ -720,7 +721,7 @@ LayerStackWidget::~LayerStackWidget() {
|
||||||
MediaPreviewWidget::MediaPreviewWidget(QWidget *parent) : TWidget(parent)
|
MediaPreviewWidget::MediaPreviewWidget(QWidget *parent) : TWidget(parent)
|
||||||
, _emojiSize(Ui::Emoji::Size(Ui::Emoji::Index() + 1) / cIntRetinaFactor()) {
|
, _emojiSize(Ui::Emoji::Size(Ui::Emoji::Index() + 1) / cIntRetinaFactor()) {
|
||||||
setAttribute(Qt::WA_TransparentForMouseEvents);
|
setAttribute(Qt::WA_TransparentForMouseEvents);
|
||||||
subscribe(FileDownload::ImageLoaded(), [this] { update(); });
|
subscribe(AuthSession::CurrentDownloaderTaskFinished(), [this] { update(); });
|
||||||
}
|
}
|
||||||
|
|
||||||
void MediaPreviewWidget::paintEvent(QPaintEvent *e) {
|
void MediaPreviewWidget::paintEvent(QPaintEvent *e) {
|
||||||
|
|
|
@ -63,6 +63,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||||
#include "mtproto/dc_options.h"
|
#include "mtproto/dc_options.h"
|
||||||
#include "core/file_utilities.h"
|
#include "core/file_utilities.h"
|
||||||
#include "auth_session.h"
|
#include "auth_session.h"
|
||||||
|
#include "window/notifications_manager.h"
|
||||||
|
|
||||||
StackItemSection::StackItemSection(std::unique_ptr<Window::SectionMemento> &&memento) : StackItem(nullptr)
|
StackItemSection::StackItemSection(std::unique_ptr<Window::SectionMemento> &&memento) : StackItem(nullptr)
|
||||||
, _memento(std::move(memento)) {
|
, _memento(std::move(memento)) {
|
||||||
|
@ -810,7 +811,6 @@ void MainWidget::deleteHistoryPart(DeleteHistoryRequest request, const MTPmessag
|
||||||
}
|
}
|
||||||
|
|
||||||
int32 offset = d.voffset.v;
|
int32 offset = d.voffset.v;
|
||||||
if (!AuthSession::Current()) return;
|
|
||||||
if (offset <= 0) {
|
if (offset <= 0) {
|
||||||
cRefReportSpamStatuses().remove(peer->id);
|
cRefReportSpamStatuses().remove(peer->id);
|
||||||
Local::writeReportSpamStatuses();
|
Local::writeReportSpamStatuses();
|
||||||
|
@ -909,7 +909,6 @@ void MainWidget::deleteAllFromUserPart(DeleteAllFromUserParams params, const MTP
|
||||||
}
|
}
|
||||||
|
|
||||||
int32 offset = d.voffset.v;
|
int32 offset = d.voffset.v;
|
||||||
if (!AuthSession::Current()) return;
|
|
||||||
if (offset > 0) {
|
if (offset > 0) {
|
||||||
MTP::send(MTPchannels_DeleteUserHistory(params.channel->inputChannel, params.from->inputUser), rpcDone(&MainWidget::deleteAllFromUserPart, params));
|
MTP::send(MTPchannels_DeleteUserHistory(params.channel->inputChannel, params.from->inputUser), rpcDone(&MainWidget::deleteAllFromUserPart, params));
|
||||||
} else if (History *h = App::historyLoaded(params.channel)) {
|
} else if (History *h = App::historyLoaded(params.channel)) {
|
||||||
|
@ -1504,7 +1503,6 @@ void MainWidget::overviewLoaded(History *history, const MTPmessages_Messages &re
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWidget::sendReadRequest(PeerData *peer, MsgId upTo) {
|
void MainWidget::sendReadRequest(PeerData *peer, MsgId upTo) {
|
||||||
if (!AuthSession::Current()) return;
|
|
||||||
if (peer->isChannel()) {
|
if (peer->isChannel()) {
|
||||||
_readRequests.insert(peer, qMakePair(MTP::send(MTPchannels_ReadHistory(peer->asChannel()->inputChannel, MTP_int(upTo)), rpcDone(&MainWidget::channelReadDone, peer), rpcFail(&MainWidget::readRequestFail, peer)), upTo));
|
_readRequests.insert(peer, qMakePair(MTP::send(MTPchannels_ReadHistory(peer->asChannel()->inputChannel, MTP_int(upTo)), rpcDone(&MainWidget::channelReadDone, peer), rpcFail(&MainWidget::readRequestFail, peer)), upTo));
|
||||||
} else {
|
} else {
|
||||||
|
@ -2106,8 +2104,6 @@ void MainWidget::fillPeerMenu(PeerData *peer, base::lambda<QAction*(const QStrin
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWidget::onViewsIncrement() {
|
void MainWidget::onViewsIncrement() {
|
||||||
if (!App::main() || !AuthSession::Current()) return;
|
|
||||||
|
|
||||||
for (ViewsIncrement::iterator i = _viewsToIncrement.begin(); i != _viewsToIncrement.cend();) {
|
for (ViewsIncrement::iterator i = _viewsToIncrement.begin(); i != _viewsToIncrement.cend();) {
|
||||||
if (_viewsIncrementRequests.contains(i.key())) {
|
if (_viewsIncrementRequests.contains(i.key())) {
|
||||||
++i;
|
++i;
|
||||||
|
@ -3628,8 +3624,6 @@ bool MainWidget::failDifference(const RPCError &error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWidget::onGetDifferenceTimeByPts() {
|
void MainWidget::onGetDifferenceTimeByPts() {
|
||||||
if (!AuthSession::Current()) return;
|
|
||||||
|
|
||||||
auto now = getms(true), wait = 0LL;
|
auto now = getms(true), wait = 0LL;
|
||||||
if (_getDifferenceTimeByPts) {
|
if (_getDifferenceTimeByPts) {
|
||||||
if (_getDifferenceTimeByPts > now) {
|
if (_getDifferenceTimeByPts > now) {
|
||||||
|
@ -3655,8 +3649,6 @@ void MainWidget::onGetDifferenceTimeByPts() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWidget::onGetDifferenceTimeAfterFail() {
|
void MainWidget::onGetDifferenceTimeAfterFail() {
|
||||||
if (!AuthSession::Current()) return;
|
|
||||||
|
|
||||||
auto now = getms(true), wait = 0LL;
|
auto now = getms(true), wait = 0LL;
|
||||||
if (_getDifferenceTimeAfterFail) {
|
if (_getDifferenceTimeAfterFail) {
|
||||||
if (_getDifferenceTimeAfterFail > now) {
|
if (_getDifferenceTimeAfterFail > now) {
|
||||||
|
@ -3731,24 +3723,21 @@ void MainWidget::mtpPing() {
|
||||||
MTP::ping();
|
MTP::ping();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWidget::start(const MTPUser &user) {
|
void MainWidget::start(const MTPUser *self) {
|
||||||
int32 uid = user.c_user().vid.v;
|
if (!self) {
|
||||||
if (!uid) {
|
MTP::send(MTPusers_GetUsers(MTP_vector<MTPInputUser>(1, MTP_inputUserSelf())), rpcDone(&MainWidget::startWithSelf));
|
||||||
LOG(("MTP Error: incorrect user received"));
|
|
||||||
App::logOut();
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (AuthSession::CurrentUserId() != uid) {
|
if (!AuthSession::Current().validateSelf(*self)) {
|
||||||
Messenger::Instance().authSessionCreate(uid);
|
return;
|
||||||
Local::writeMtpData();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Local::readSavedPeers();
|
Local::readSavedPeers();
|
||||||
|
|
||||||
cSetOtherOnline(0);
|
cSetOtherOnline(0);
|
||||||
if (auto self = App::feedUsers(MTP_vector<MTPUser>(1, user))) {
|
if (auto user = App::feedUsers(MTP_vector<MTPUser>(1, *self))) {
|
||||||
self->loadUserpic();
|
user->loadUserpic();
|
||||||
}
|
}
|
||||||
|
|
||||||
MTP::send(MTPupdates_GetState(), rpcDone(&MainWidget::gotState));
|
MTP::send(MTPupdates_GetState(), rpcDone(&MainWidget::gotState));
|
||||||
update();
|
update();
|
||||||
|
|
||||||
|
@ -4039,12 +4028,13 @@ bool MainWidget::inviteImportFail(const RPCError &error) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWidget::startFull(const MTPVector<MTPUser> &users) {
|
void MainWidget::startWithSelf(const MTPVector<MTPUser> &users) {
|
||||||
const auto &v(users.c_vector().v);
|
auto &v = users.c_vector().v;
|
||||||
if (v.isEmpty() || v[0].type() != mtpc_user || !v[0].c_user().is_self()) { // wtf?..
|
if (v.isEmpty()) {
|
||||||
|
LOG(("Auth Error: self user not received."));
|
||||||
return App::logOutDelayed();
|
return App::logOutDelayed();
|
||||||
}
|
}
|
||||||
start(v[0]);
|
start(&v[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWidget::applyNotifySetting(const MTPNotifyPeer &peer, const MTPPeerNotifySettings &settings, History *h) {
|
void MainWidget::applyNotifySetting(const MTPNotifyPeer &peer, const MTPPeerNotifySettings &settings, History *h) {
|
||||||
|
@ -4100,7 +4090,7 @@ void MainWidget::applyNotifySetting(const MTPNotifyPeer &peer, const MTPPeerNoti
|
||||||
if (!h) h = App::history(updatePeer->id);
|
if (!h) h = App::history(updatePeer->id);
|
||||||
int32 changeIn = 0;
|
int32 changeIn = 0;
|
||||||
if (isNotifyMuted(setTo, &changeIn)) {
|
if (isNotifyMuted(setTo, &changeIn)) {
|
||||||
App::wnd()->notifyClear(h);
|
AuthSession::Current().notifications()->clearFromHistory(h);
|
||||||
h->setMute(true);
|
h->setMute(true);
|
||||||
App::regMuted(updatePeer, changeIn);
|
App::regMuted(updatePeer, changeIn);
|
||||||
} else {
|
} else {
|
||||||
|
@ -4379,7 +4369,7 @@ void MainWidget::checkIdleFinish() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWidget::updateReceived(const mtpPrime *from, const mtpPrime *end) {
|
void MainWidget::updateReceived(const mtpPrime *from, const mtpPrime *end) {
|
||||||
if (end <= from || !AuthSession::Current()) return;
|
if (end <= from) return;
|
||||||
|
|
||||||
App::wnd()->checkAutoLock();
|
App::wnd()->checkAutoLock();
|
||||||
|
|
||||||
|
@ -4638,8 +4628,6 @@ void MainWidget::feedUpdates(const MTPUpdates &updates, uint64 randomId) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWidget::feedUpdate(const MTPUpdate &update) {
|
void MainWidget::feedUpdate(const MTPUpdate &update) {
|
||||||
if (!AuthSession::Current()) return;
|
|
||||||
|
|
||||||
switch (update.type()) {
|
switch (update.type()) {
|
||||||
case mtpc_updateNewMessage: {
|
case mtpc_updateNewMessage: {
|
||||||
auto &d = update.c_updateNewMessage();
|
auto &d = update.c_updateNewMessage();
|
||||||
|
|
|
@ -158,7 +158,7 @@ public:
|
||||||
|
|
||||||
void showAnimated(const QPixmap &bgAnimCache, bool back = false);
|
void showAnimated(const QPixmap &bgAnimCache, bool back = false);
|
||||||
|
|
||||||
void start(const MTPUser &user);
|
void start(const MTPUser *self = nullptr);
|
||||||
|
|
||||||
void checkStartUrl();
|
void checkStartUrl();
|
||||||
void openLocalUrl(const QString &str);
|
void openLocalUrl(const QString &str);
|
||||||
|
@ -166,7 +166,6 @@ public:
|
||||||
void joinGroupByHash(const QString &hash);
|
void joinGroupByHash(const QString &hash);
|
||||||
void stickersBox(const MTPInputStickerSet &set);
|
void stickersBox(const MTPInputStickerSet &set);
|
||||||
|
|
||||||
void startFull(const MTPVector<MTPUser> &users);
|
|
||||||
bool started();
|
bool started();
|
||||||
void applyNotifySetting(const MTPNotifyPeer &peer, const MTPPeerNotifySettings &settings, History *history = 0);
|
void applyNotifySetting(const MTPNotifyPeer &peer, const MTPPeerNotifySettings &settings, History *history = 0);
|
||||||
|
|
||||||
|
@ -518,6 +517,8 @@ private:
|
||||||
Window::SectionSlideParams prepareOverviewAnimation();
|
Window::SectionSlideParams prepareOverviewAnimation();
|
||||||
Window::SectionSlideParams prepareDialogsAnimation();
|
Window::SectionSlideParams prepareDialogsAnimation();
|
||||||
|
|
||||||
|
void startWithSelf(const MTPVector<MTPUser> &users);
|
||||||
|
|
||||||
void saveSectionInStack();
|
void saveSectionInStack();
|
||||||
|
|
||||||
bool _started = false;
|
bool _started = false;
|
||||||
|
|
|
@ -100,17 +100,6 @@ MainWindow::MainWindow() {
|
||||||
iconbig32 = iconbig256.scaledToWidth(32, Qt::SmoothTransformation);
|
iconbig32 = iconbig256.scaledToWidth(32, Qt::SmoothTransformation);
|
||||||
iconbig64 = iconbig256.scaledToWidth(64, Qt::SmoothTransformation);
|
iconbig64 = iconbig256.scaledToWidth(64, Qt::SmoothTransformation);
|
||||||
|
|
||||||
subscribe(Global::RefNotifySettingsChanged(), [this](Notify::ChangeType type) {
|
|
||||||
if (type == Notify::ChangeType::DesktopEnabled) {
|
|
||||||
updateTrayMenu();
|
|
||||||
notifyClear();
|
|
||||||
} else if (type == Notify::ChangeType::ViewParams) {
|
|
||||||
notifyUpdateAll();
|
|
||||||
} else if (type == Notify::ChangeType::IncludeMuted) {
|
|
||||||
Notify::unreadCounterUpdated();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
resize(st::windowDefaultWidth, st::windowDefaultHeight);
|
resize(st::windowDefaultWidth, st::windowDefaultHeight);
|
||||||
|
|
||||||
setLocale(QLocale(QLocale::English, QLocale::UnitedStates));
|
setLocale(QLocale(QLocale::English, QLocale::UnitedStates));
|
||||||
|
@ -118,8 +107,6 @@ MainWindow::MainWindow() {
|
||||||
_inactiveTimer.setSingleShot(true);
|
_inactiveTimer.setSingleShot(true);
|
||||||
connect(&_inactiveTimer, SIGNAL(timeout()), this, SLOT(onInactiveTimer()));
|
connect(&_inactiveTimer, SIGNAL(timeout()), this, SLOT(onInactiveTimer()));
|
||||||
|
|
||||||
connect(&_notifyWaitTimer, SIGNAL(timeout()), this, SLOT(notifyShowNext()));
|
|
||||||
|
|
||||||
connect(&_autoLockTimer, SIGNAL(timeout()), this, SLOT(checkAutoLock()));
|
connect(&_autoLockTimer, SIGNAL(timeout()), this, SLOT(checkAutoLock()));
|
||||||
|
|
||||||
subscribe(Global::RefSelfChanged(), [this]() { updateGlobalMenu(); });
|
subscribe(Global::RefSelfChanged(), [this]() { updateGlobalMenu(); });
|
||||||
|
@ -156,7 +143,7 @@ void MainWindow::onStateChanged(Qt::WindowState state) {
|
||||||
updateIsActive((state == Qt::WindowMinimized) ? Global::OfflineBlurTimeout() : Global::OnlineFocusTimeout());
|
updateIsActive((state == Qt::WindowMinimized) ? Global::OfflineBlurTimeout() : Global::OnlineFocusTimeout());
|
||||||
|
|
||||||
psUpdateSysMenu(state);
|
psUpdateSysMenu(state);
|
||||||
if (state == Qt::WindowMinimized && cWorkMode() == dbiwmTrayOnly) {
|
if (state == Qt::WindowMinimized && Global::WorkMode().value() == dbiwmTrayOnly) {
|
||||||
App::wnd()->minimizeToTray();
|
App::wnd()->minimizeToTray();
|
||||||
}
|
}
|
||||||
savePosition(state);
|
savePosition(state);
|
||||||
|
@ -200,7 +187,7 @@ void MainWindow::firstShow() {
|
||||||
trayIconMenu->addAction(notificationActionText, this, SLOT(toggleDisplayNotifyFromTray()))->setEnabled(true);
|
trayIconMenu->addAction(notificationActionText, this, SLOT(toggleDisplayNotifyFromTray()))->setEnabled(true);
|
||||||
trayIconMenu->addAction(lang(lng_quit_from_tray), this, SLOT(quitFromTray()))->setEnabled(true);
|
trayIconMenu->addAction(lang(lng_quit_from_tray), this, SLOT(quitFromTray()))->setEnabled(true);
|
||||||
}
|
}
|
||||||
psUpdateWorkmode();
|
workmodeUpdated(Global::WorkMode().value());
|
||||||
|
|
||||||
psFirstShow();
|
psFirstShow();
|
||||||
updateTrayMenu();
|
updateTrayMenu();
|
||||||
|
@ -241,7 +228,7 @@ void MainWindow::clearPasscode() {
|
||||||
} else {
|
} else {
|
||||||
_main->showAnimated(bg, true);
|
_main->showAnimated(bg, true);
|
||||||
}
|
}
|
||||||
notifyUpdateAll();
|
AuthSession::Current().notifications()->updateAll();
|
||||||
updateGlobalMenu();
|
updateGlobalMenu();
|
||||||
|
|
||||||
if (_main) {
|
if (_main) {
|
||||||
|
@ -265,7 +252,9 @@ void MainWindow::setupPasscode() {
|
||||||
setInnerFocus();
|
setInnerFocus();
|
||||||
}
|
}
|
||||||
_shouldLockAt = 0;
|
_shouldLockAt = 0;
|
||||||
notifyUpdateAll();
|
if (AuthSession::Exists()) {
|
||||||
|
AuthSession::Current().notifications()->updateAll();
|
||||||
|
}
|
||||||
updateGlobalMenu();
|
updateGlobalMenu();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -360,6 +349,9 @@ void MainWindow::setupMain(const MTPUser *self) {
|
||||||
auto bg = animated ? grabInner() : QPixmap();
|
auto bg = animated ? grabInner() : QPixmap();
|
||||||
|
|
||||||
clearWidgets();
|
clearWidgets();
|
||||||
|
|
||||||
|
t_assert(AuthSession::Exists());
|
||||||
|
|
||||||
_main.create(bodyWidget());
|
_main.create(bodyWidget());
|
||||||
_main->show();
|
_main->show();
|
||||||
updateControlsGeometry();
|
updateControlsGeometry();
|
||||||
|
@ -369,11 +361,7 @@ void MainWindow::setupMain(const MTPUser *self) {
|
||||||
} else {
|
} else {
|
||||||
_main->activate();
|
_main->activate();
|
||||||
}
|
}
|
||||||
if (self) {
|
_main->start(self);
|
||||||
_main->start(*self);
|
|
||||||
} else {
|
|
||||||
MTP::send(MTPusers_GetUsers(MTP_vector<MTPInputUser>(1, MTP_inputUserSelf())), _main->rpcDone(&MainWidget::startFull));
|
|
||||||
}
|
|
||||||
|
|
||||||
fixOrder();
|
fixOrder();
|
||||||
|
|
||||||
|
@ -573,7 +561,7 @@ bool MainWindow::doWeReadServerHistory() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::checkHistoryActivation() {
|
void MainWindow::checkHistoryActivation() {
|
||||||
if (_main && AuthSession::Current() && doWeReadServerHistory()) {
|
if (_main && doWeReadServerHistory()) {
|
||||||
_main->markActiveHistoryAsRead();
|
_main->markActiveHistoryAsRead();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -842,9 +830,9 @@ void MainWindow::toggleDisplayNotifyFromTray() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Local::writeUserSettings();
|
Local::writeUserSettings();
|
||||||
Global::RefNotifySettingsChanged().notify(Notify::ChangeType::DesktopEnabled);
|
AuthSession::Current().notifications()->settingsChanged().notify(Window::Notifications::ChangeType::DesktopEnabled);
|
||||||
if (soundNotifyChanged) {
|
if (soundNotifyChanged) {
|
||||||
Global::RefNotifySettingsChanged().notify(Notify::ChangeType::SoundEnabled);
|
AuthSession::Current().notifications()->settingsChanged().notify(Window::Notifications::ChangeType::SoundEnabled);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -854,7 +842,7 @@ void MainWindow::closeEvent(QCloseEvent *e) {
|
||||||
App::quit();
|
App::quit();
|
||||||
} else {
|
} else {
|
||||||
e->ignore();
|
e->ignore();
|
||||||
if (!AuthSession::Current() || !Ui::hideWindowNoQuit()) {
|
if (!AuthSession::Exists() || !Ui::hideWindowNoQuit()) {
|
||||||
App::quit();
|
App::quit();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -919,305 +907,10 @@ void MainWindow::onClearFailed(int task, void *manager) {
|
||||||
emit tempDirClearFailed(task);
|
emit tempDirClearFailed(task);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::notifySchedule(History *history, HistoryItem *item) {
|
|
||||||
if (App::quitting() || !history->currentNotification() || !App::api()) return;
|
|
||||||
|
|
||||||
PeerData *notifyByFrom = (!history->peer->isUser() && item->mentionsMe()) ? item->from() : 0;
|
|
||||||
|
|
||||||
if (item->isSilent()) {
|
|
||||||
history->popNotification(item);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool haveSetting = (history->peer->notify != UnknownNotifySettings);
|
|
||||||
if (haveSetting) {
|
|
||||||
if (history->peer->notify != EmptyNotifySettings && history->peer->notify->mute > unixtime()) {
|
|
||||||
if (notifyByFrom) {
|
|
||||||
haveSetting = (item->from()->notify != UnknownNotifySettings);
|
|
||||||
if (haveSetting) {
|
|
||||||
if (notifyByFrom->notify != EmptyNotifySettings && notifyByFrom->notify->mute > unixtime()) {
|
|
||||||
history->popNotification(item);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
App::api()->requestNotifySetting(notifyByFrom);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
history->popNotification(item);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (notifyByFrom && notifyByFrom->notify == UnknownNotifySettings) {
|
|
||||||
App::api()->requestNotifySetting(notifyByFrom);
|
|
||||||
}
|
|
||||||
App::api()->requestNotifySetting(history->peer);
|
|
||||||
}
|
|
||||||
if (!item->notificationReady()) {
|
|
||||||
haveSetting = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
int delay = item->Has<HistoryMessageForwarded>() ? 500 : 100, t = unixtime();
|
|
||||||
auto ms = getms(true);
|
|
||||||
bool isOnline = _main->lastWasOnline(), otherNotOld = ((cOtherOnline() * 1000LL) + Global::OnlineCloudTimeout() > t * 1000LL);
|
|
||||||
bool otherLaterThanMe = (cOtherOnline() * 1000LL + (ms - _main->lastSetOnline()) > t * 1000LL);
|
|
||||||
if (!isOnline && otherNotOld && otherLaterThanMe) {
|
|
||||||
delay = Global::NotifyCloudDelay();
|
|
||||||
} else if (cOtherOnline() >= t) {
|
|
||||||
delay = Global::NotifyDefaultDelay();
|
|
||||||
}
|
|
||||||
|
|
||||||
auto when = ms + delay;
|
|
||||||
_notifyWhenAlerts[history].insert(when, notifyByFrom);
|
|
||||||
if (Global::DesktopNotify() && !Platform::Notifications::SkipToast()) {
|
|
||||||
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 ? &_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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void MainWindow::notifyClear(History *history) {
|
|
||||||
if (!history) {
|
|
||||||
Window::Notifications::GetManager()->clearAll();
|
|
||||||
|
|
||||||
for (auto i = _notifyWhenMaps.cbegin(), e = _notifyWhenMaps.cend(); i != e; ++i) {
|
|
||||||
i.key()->clearNotifications();
|
|
||||||
}
|
|
||||||
_notifyWhenMaps.clear();
|
|
||||||
_notifyWhenAlerts.clear();
|
|
||||||
_notifyWaiters.clear();
|
|
||||||
_notifySettingWaiters.clear();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Window::Notifications::GetManager()->clearFromHistory(history);
|
|
||||||
|
|
||||||
history->clearNotifications();
|
|
||||||
_notifyWhenMaps.remove(history);
|
|
||||||
_notifyWhenAlerts.remove(history);
|
|
||||||
_notifyWaiters.remove(history);
|
|
||||||
_notifySettingWaiters.remove(history);
|
|
||||||
|
|
||||||
_notifyWaitTimer.stop();
|
|
||||||
notifyShowNext();
|
|
||||||
}
|
|
||||||
|
|
||||||
void MainWindow::notifyClearFast() {
|
|
||||||
Window::Notifications::GetManager()->clearAllFast();
|
|
||||||
|
|
||||||
_notifyWhenMaps.clear();
|
|
||||||
_notifyWhenAlerts.clear();
|
|
||||||
_notifyWaiters.clear();
|
|
||||||
_notifySettingWaiters.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
void MainWindow::notifySettingGot() {
|
|
||||||
int32 t = unixtime();
|
|
||||||
for (NotifyWaiters::iterator i = _notifySettingWaiters.begin(); i != _notifySettingWaiters.end();) {
|
|
||||||
History *history = i.key();
|
|
||||||
bool loaded = false, muted = false;
|
|
||||||
if (history->peer->notify != UnknownNotifySettings) {
|
|
||||||
if (history->peer->notify == EmptyNotifySettings || history->peer->notify->mute <= t) {
|
|
||||||
loaded = true;
|
|
||||||
} else if (PeerData *from = i.value().notifyByFrom) {
|
|
||||||
if (from->notify != UnknownNotifySettings) {
|
|
||||||
if (from->notify == EmptyNotifySettings || from->notify->mute <= t) {
|
|
||||||
loaded = true;
|
|
||||||
} else {
|
|
||||||
loaded = muted = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
loaded = muted = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (loaded) {
|
|
||||||
if (HistoryItem *item = App::histItemById(history->channelId(), i.value().msg)) {
|
|
||||||
if (!item->notificationReady()) {
|
|
||||||
loaded = false;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
muted = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (loaded) {
|
|
||||||
if (!muted) {
|
|
||||||
_notifyWaiters.insert(i.key(), i.value());
|
|
||||||
}
|
|
||||||
i = _notifySettingWaiters.erase(i);
|
|
||||||
} else {
|
|
||||||
++i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_notifyWaitTimer.stop();
|
|
||||||
notifyShowNext();
|
|
||||||
}
|
|
||||||
|
|
||||||
void MainWindow::notifyShowNext() {
|
|
||||||
if (App::quitting()) return;
|
|
||||||
|
|
||||||
auto ms = getms(true), nextAlert = 0LL;
|
|
||||||
bool alert = false;
|
|
||||||
int32 now = unixtime();
|
|
||||||
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
|
|
||||||
i.value().erase(i.value().begin());
|
|
||||||
}
|
|
||||||
if (n == EmptyNotifySettings || (n != UnknownNotifySettings && n->mute <= now)) {
|
|
||||||
alert = true;
|
|
||||||
} else if (f == EmptyNotifySettings || (f != UnknownNotifySettings && f->mute <= now)) { // notify by from()
|
|
||||||
alert = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (i.value().isEmpty()) {
|
|
||||||
i = _notifyWhenAlerts.erase(i);
|
|
||||||
} else {
|
|
||||||
if (!nextAlert || nextAlert > i.value().begin().key()) {
|
|
||||||
nextAlert = i.value().begin().key();
|
|
||||||
}
|
|
||||||
++i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (alert) {
|
|
||||||
psFlash();
|
|
||||||
App::playSound();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_notifyWaiters.isEmpty() || !Global::DesktopNotify() || Platform::Notifications::SkipToast()) {
|
|
||||||
if (nextAlert) {
|
|
||||||
_notifyWaitTimer.start(nextAlert - ms);
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
while (true) {
|
|
||||||
auto next = 0LL;
|
|
||||||
HistoryItem *notifyItem = 0;
|
|
||||||
History *notifyHistory = 0;
|
|
||||||
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()) {
|
|
||||||
history->clearNotifications();
|
|
||||||
i = _notifyWaiters.erase(i);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
do {
|
|
||||||
NotifyWhenMap::const_iterator k = j.value().constFind(history->currentNotification()->id);
|
|
||||||
if (k != j.value().cend()) {
|
|
||||||
i.value().msg = k.key();
|
|
||||||
i.value().when = k.value();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
history->skipNotification();
|
|
||||||
} while (history->currentNotification());
|
|
||||||
}
|
|
||||||
if (!history->currentNotification()) {
|
|
||||||
_notifyWhenMaps.remove(history);
|
|
||||||
i = _notifyWaiters.erase(i);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
auto when = i.value().when;
|
|
||||||
if (!notifyItem || next > when) {
|
|
||||||
next = when;
|
|
||||||
notifyItem = history->currentNotification();
|
|
||||||
notifyHistory = history;
|
|
||||||
}
|
|
||||||
++i;
|
|
||||||
}
|
|
||||||
if (notifyItem) {
|
|
||||||
if (next > ms) {
|
|
||||||
if (nextAlert && nextAlert < next) {
|
|
||||||
next = nextAlert;
|
|
||||||
nextAlert = 0;
|
|
||||||
}
|
|
||||||
_notifyWaitTimer.start(next - ms);
|
|
||||||
break;
|
|
||||||
} else {
|
|
||||||
HistoryItem *fwd = notifyItem->Has<HistoryMessageForwarded>() ? notifyItem : nullptr; // forwarded notify grouping
|
|
||||||
int32 fwdCount = 1;
|
|
||||||
|
|
||||||
auto ms = getms(true);
|
|
||||||
History *history = notifyItem->history();
|
|
||||||
NotifyWhenMaps::iterator j = _notifyWhenMaps.find(history);
|
|
||||||
if (j == _notifyWhenMaps.cend()) {
|
|
||||||
history->clearNotifications();
|
|
||||||
} else {
|
|
||||||
HistoryItem *nextNotify = 0;
|
|
||||||
do {
|
|
||||||
history->skipNotification();
|
|
||||||
if (!history->hasNotification()) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
j.value().remove((fwd ? fwd : notifyItem)->id);
|
|
||||||
do {
|
|
||||||
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));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
history->skipNotification();
|
|
||||||
} while (history->hasNotification());
|
|
||||||
if (nextNotify) {
|
|
||||||
if (fwd) {
|
|
||||||
HistoryItem *nextFwd = nextNotify->Has<HistoryMessageForwarded>() ? nextNotify : nullptr;
|
|
||||||
if (nextFwd && fwd->author() == nextFwd->author() && qAbs(int64(nextFwd->date.toTime_t()) - int64(fwd->date.toTime_t())) < 2) {
|
|
||||||
fwd = nextFwd;
|
|
||||||
++fwdCount;
|
|
||||||
} else {
|
|
||||||
nextNotify = 0;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
nextNotify = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} while (nextNotify);
|
|
||||||
}
|
|
||||||
|
|
||||||
Window::Notifications::GetManager()->showNotification(notifyItem, fwdCount);
|
|
||||||
|
|
||||||
if (!history->hasNotification()) {
|
|
||||||
_notifyWaiters.remove(history);
|
|
||||||
_notifyWhenMaps.remove(history);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (nextAlert) {
|
|
||||||
_notifyWaitTimer.start(nextAlert - ms);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void MainWindow::app_activateClickHandler(ClickHandlerPtr handler, Qt::MouseButton button) {
|
void MainWindow::app_activateClickHandler(ClickHandlerPtr handler, Qt::MouseButton button) {
|
||||||
handler->onClick(button);
|
handler->onClick(button);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::notifyUpdateAll() {
|
|
||||||
Window::Notifications::GetManager()->updateAll();
|
|
||||||
}
|
|
||||||
|
|
||||||
QImage MainWindow::iconLarge() const {
|
QImage MainWindow::iconLarge() const {
|
||||||
return iconbig256;
|
return iconbig256;
|
||||||
}
|
}
|
||||||
|
@ -1346,7 +1039,6 @@ void MainWindow::updateIsActiveHook() {
|
||||||
}
|
}
|
||||||
|
|
||||||
MainWindow::~MainWindow() {
|
MainWindow::~MainWindow() {
|
||||||
notifyClearFast();
|
|
||||||
if (_clearManager) {
|
if (_clearManager) {
|
||||||
_clearManager->stop();
|
_clearManager->stop();
|
||||||
_clearManager = nullptr;
|
_clearManager = nullptr;
|
||||||
|
|
|
@ -87,7 +87,7 @@ public:
|
||||||
void clearPasscode();
|
void clearPasscode();
|
||||||
void checkAutoLockIn(int msec);
|
void checkAutoLockIn(int msec);
|
||||||
void setupIntro();
|
void setupIntro();
|
||||||
void setupMain(const MTPUser *user = 0);
|
void setupMain(const MTPUser *user = nullptr);
|
||||||
void serviceNotification(const TextWithEntities &message, const MTPMessageMedia &media = MTP_messageMediaEmpty(), int32 date = 0, bool force = false);
|
void serviceNotification(const TextWithEntities &message, const MTPMessageMedia &media = MTP_messageMediaEmpty(), int32 date = 0, bool force = false);
|
||||||
void serviceNotificationLocal(QString text);
|
void serviceNotificationLocal(QString text);
|
||||||
void sendServiceHistoryRequest();
|
void sendServiceHistoryRequest();
|
||||||
|
@ -120,12 +120,6 @@ public:
|
||||||
TempDirState localStorageState();
|
TempDirState localStorageState();
|
||||||
void tempDirDelete(int task);
|
void tempDirDelete(int task);
|
||||||
|
|
||||||
void notifySettingGot();
|
|
||||||
void notifySchedule(History *history, HistoryItem *item);
|
|
||||||
void notifyClear(History *history = 0);
|
|
||||||
void notifyClearFast();
|
|
||||||
void notifyUpdateAll();
|
|
||||||
|
|
||||||
QImage iconLarge() const;
|
QImage iconLarge() const;
|
||||||
|
|
||||||
void sendPaths();
|
void sendPaths();
|
||||||
|
@ -183,8 +177,6 @@ public slots:
|
||||||
void onClearFinished(int task, void *manager);
|
void onClearFinished(int task, void *manager);
|
||||||
void onClearFailed(int task, void *manager);
|
void onClearFailed(int task, void *manager);
|
||||||
|
|
||||||
void notifyShowNext();
|
|
||||||
|
|
||||||
void onShowAddContact();
|
void onShowAddContact();
|
||||||
void onShowNewGroup();
|
void onShowNewGroup();
|
||||||
void onShowNewChannel();
|
void onShowNewChannel();
|
||||||
|
@ -240,28 +232,6 @@ private:
|
||||||
SingleTimer _autoLockTimer;
|
SingleTimer _autoLockTimer;
|
||||||
TimeMs _shouldLockAt = 0;
|
TimeMs _shouldLockAt = 0;
|
||||||
|
|
||||||
using NotifyWhenMap = QMap<MsgId, TimeMs>;
|
|
||||||
using NotifyWhenMaps = QMap<History*, NotifyWhenMap>;
|
|
||||||
NotifyWhenMaps _notifyWhenMaps;
|
|
||||||
struct NotifyWaiter {
|
|
||||||
NotifyWaiter(MsgId msg, TimeMs when, PeerData *notifyByFrom)
|
|
||||||
: msg(msg)
|
|
||||||
, when(when)
|
|
||||||
, notifyByFrom(notifyByFrom) {
|
|
||||||
}
|
|
||||||
MsgId msg;
|
|
||||||
TimeMs when;
|
|
||||||
PeerData *notifyByFrom;
|
|
||||||
};
|
|
||||||
using NotifyWaiters = QMap<History*, NotifyWaiter>;
|
|
||||||
NotifyWaiters _notifyWaiters;
|
|
||||||
NotifyWaiters _notifySettingWaiters;
|
|
||||||
SingleTimer _notifyWaitTimer;
|
|
||||||
|
|
||||||
using NotifyWhenAlert = QMap<TimeMs, PeerData*>;
|
|
||||||
using NotifyWhenAlerts = QMap<History*, NotifyWhenAlert>;
|
|
||||||
NotifyWhenAlerts _notifyWhenAlerts;
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class PreLaunchWindow : public TWidget {
|
class PreLaunchWindow : public TWidget {
|
||||||
|
|
|
@ -36,6 +36,9 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||||
#include "window/themes/window_theme_preview.h"
|
#include "window/themes/window_theme_preview.h"
|
||||||
#include "core/task_queue.h"
|
#include "core/task_queue.h"
|
||||||
#include "observer_peer.h"
|
#include "observer_peer.h"
|
||||||
|
#include "auth_session.h"
|
||||||
|
#include "messenger.h"
|
||||||
|
#include "storage/file_download.h"
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
|
@ -86,10 +89,15 @@ MediaView::MediaView(QWidget*) : TWidget(nullptr)
|
||||||
|
|
||||||
connect(QApplication::desktop(), SIGNAL(resized(int)), this, SLOT(onScreenResized(int)));
|
connect(QApplication::desktop(), SIGNAL(resized(int)), this, SLOT(onScreenResized(int)));
|
||||||
|
|
||||||
subscribe(FileDownload::ImageLoaded(), [this] {
|
// While we have one mediaview for all authsessions we have to do this.
|
||||||
if (!isHidden()) {
|
subscribe(Messenger::Instance().authSessionChanged(), [this] {
|
||||||
updateControls();
|
if (!AuthSession::Exists()) return;
|
||||||
}
|
|
||||||
|
subscribe(AuthSession::CurrentDownloaderTaskFinished(), [this] {
|
||||||
|
if (!isHidden()) {
|
||||||
|
updateControls();
|
||||||
|
}
|
||||||
|
});
|
||||||
});
|
});
|
||||||
auto observeEvents = Notify::PeerUpdate::Flag::SharedMediaChanged;
|
auto observeEvents = Notify::PeerUpdate::Flag::SharedMediaChanged;
|
||||||
subscribe(Notify::PeerUpdated(), Notify::PeerUpdatedHandler(observeEvents, [this](const Notify::PeerUpdate &update) {
|
subscribe(Notify::PeerUpdated(), Notify::PeerUpdatedHandler(observeEvents, [this](const Notify::PeerUpdate &update) {
|
||||||
|
@ -1155,7 +1163,7 @@ void MediaView::displayPhoto(PhotoData *photo, HistoryItem *item) {
|
||||||
}
|
}
|
||||||
|
|
||||||
_zoomToScreen = 0;
|
_zoomToScreen = 0;
|
||||||
MTP::clearLoaderPriorities();
|
AuthSession::Current().downloader()->clearPriorities();
|
||||||
_full = -1;
|
_full = -1;
|
||||||
_current = QPixmap();
|
_current = QPixmap();
|
||||||
_down = OverNone;
|
_down = OverNone;
|
||||||
|
|
|
@ -86,7 +86,6 @@ Messenger::Messenger() : QObject()
|
||||||
anim::startManager();
|
anim::startManager();
|
||||||
historyInit();
|
historyInit();
|
||||||
Media::Player::start();
|
Media::Player::start();
|
||||||
Window::Notifications::Start();
|
|
||||||
|
|
||||||
DEBUG_LOG(("Application Info: inited..."));
|
DEBUG_LOG(("Application Info: inited..."));
|
||||||
|
|
||||||
|
@ -130,7 +129,7 @@ Messenger::Messenger() : QObject()
|
||||||
if (state == Local::ReadMapPassNeeded) {
|
if (state == Local::ReadMapPassNeeded) {
|
||||||
_window->setupPasscode();
|
_window->setupPasscode();
|
||||||
} else {
|
} else {
|
||||||
if (AuthSession::Current()) {
|
if (AuthSession::Exists()) {
|
||||||
_window->setupMain();
|
_window->setupMain();
|
||||||
} else {
|
} else {
|
||||||
_window->setupIntro();
|
_window->setupIntro();
|
||||||
|
@ -196,7 +195,7 @@ QByteArray Messenger::serializeMtpAuthorization() const {
|
||||||
QDataStream stream(&buffer);
|
QDataStream stream(&buffer);
|
||||||
stream.setVersion(QDataStream::Qt_5_1);
|
stream.setVersion(QDataStream::Qt_5_1);
|
||||||
|
|
||||||
stream << qint32(AuthSession::CurrentUserId()) << qint32(mainDcId);
|
stream << qint32(AuthSession::Exists() ? AuthSession::CurrentUserId() : 0) << qint32(mainDcId);
|
||||||
writeKeys(stream, keys);
|
writeKeys(stream, keys);
|
||||||
writeKeys(stream, keysToDestroy);
|
writeKeys(stream, keysToDestroy);
|
||||||
}
|
}
|
||||||
|
@ -433,7 +432,7 @@ bool Messenger::peerPhotoFail(PeerId peer, const RPCError &error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Messenger::peerClearPhoto(PeerId id) {
|
void Messenger::peerClearPhoto(PeerId id) {
|
||||||
if (!AuthSession::Current()) return;
|
if (!AuthSession::Exists()) return;
|
||||||
|
|
||||||
if (id == AuthSession::CurrentUserPeerId()) {
|
if (id == AuthSession::CurrentUserPeerId()) {
|
||||||
MTP::send(MTPphotos_UpdateProfilePhoto(MTP_inputPhotoEmpty()), rpcDone(&Messenger::selfPhotoCleared), rpcFail(&Messenger::peerPhotoFail, id));
|
MTP::send(MTPphotos_UpdateProfilePhoto(MTP_inputPhotoEmpty()), rpcDone(&Messenger::selfPhotoCleared), rpcFail(&Messenger::peerPhotoFail, id));
|
||||||
|
@ -525,7 +524,7 @@ void Messenger::killDownloadSessions() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Messenger::photoUpdated(const FullMsgId &msgId, bool silent, const MTPInputFile &file) {
|
void Messenger::photoUpdated(const FullMsgId &msgId, bool silent, const MTPInputFile &file) {
|
||||||
if (!AuthSession::Current()) return;
|
if (!AuthSession::Exists()) return;
|
||||||
|
|
||||||
auto i = photoUpdates.find(msgId);
|
auto i = photoUpdates.find(msgId);
|
||||||
if (i != photoUpdates.end()) {
|
if (i != photoUpdates.end()) {
|
||||||
|
@ -583,10 +582,12 @@ void Messenger::onSwitchTestMode() {
|
||||||
|
|
||||||
void Messenger::authSessionCreate(UserId userId) {
|
void Messenger::authSessionCreate(UserId userId) {
|
||||||
_authSession = std::make_unique<AuthSession>(userId);
|
_authSession = std::make_unique<AuthSession>(userId);
|
||||||
|
authSessionChanged().notify();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Messenger::authSessionDestroy() {
|
void Messenger::authSessionDestroy() {
|
||||||
_authSession.reset();
|
_authSession.reset();
|
||||||
|
authSessionChanged().notify();
|
||||||
}
|
}
|
||||||
|
|
||||||
FileUploader *Messenger::uploader() {
|
FileUploader *Messenger::uploader() {
|
||||||
|
@ -656,6 +657,7 @@ void Messenger::prepareToDestroy() {
|
||||||
|
|
||||||
// Some MTP requests can be cancelled from data clearing.
|
// Some MTP requests can be cancelled from data clearing.
|
||||||
App::clearHistories();
|
App::clearHistories();
|
||||||
|
authSessionDestroy();
|
||||||
_delayedDestroyedLoaders.clear();
|
_delayedDestroyedLoaders.clear();
|
||||||
|
|
||||||
_mtproto.reset();
|
_mtproto.reset();
|
||||||
|
@ -668,8 +670,6 @@ Messenger::~Messenger() {
|
||||||
|
|
||||||
Shortcuts::finish();
|
Shortcuts::finish();
|
||||||
|
|
||||||
Window::Notifications::Finish();
|
|
||||||
|
|
||||||
anim::stopManager();
|
anim::stopManager();
|
||||||
|
|
||||||
stopWebLoadManager();
|
stopWebLoadManager();
|
||||||
|
|
|
@ -32,7 +32,7 @@ class MainWidget;
|
||||||
class FileUploader;
|
class FileUploader;
|
||||||
class Translator;
|
class Translator;
|
||||||
|
|
||||||
class Messenger : public QObject, public RPCSender, private base::Subscriber {
|
class Messenger final : public QObject, public RPCSender, private base::Subscriber {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@ -73,6 +73,9 @@ public:
|
||||||
}
|
}
|
||||||
void authSessionCreate(UserId userId);
|
void authSessionCreate(UserId userId);
|
||||||
void authSessionDestroy();
|
void authSessionDestroy();
|
||||||
|
base::Observable<void> &authSessionChanged() {
|
||||||
|
return _authSessionChanged;
|
||||||
|
}
|
||||||
|
|
||||||
FileUploader *uploader();
|
FileUploader *uploader();
|
||||||
void uploadProfilePhoto(const QImage &tosend, const PeerId &peerId);
|
void uploadProfilePhoto(const QImage &tosend, const PeerId &peerId);
|
||||||
|
@ -145,6 +148,7 @@ private:
|
||||||
std::unique_ptr<MTP::Instance> _mtproto;
|
std::unique_ptr<MTP::Instance> _mtproto;
|
||||||
std::unique_ptr<MTP::Instance> _mtprotoForKeysDestroy;
|
std::unique_ptr<MTP::Instance> _mtprotoForKeysDestroy;
|
||||||
std::unique_ptr<AuthSession> _authSession;
|
std::unique_ptr<AuthSession> _authSession;
|
||||||
|
base::Observable<void> _authSessionChanged;
|
||||||
|
|
||||||
SingleDelayedCall _delayedLoadersDestroyer;
|
SingleDelayedCall _delayedLoadersDestroyer;
|
||||||
std::vector<std::unique_ptr<FileLoader>> _delayedDestroyedLoaders;
|
std::vector<std::unique_ptr<FileLoader>> _delayedDestroyedLoaders;
|
||||||
|
|
|
@ -796,7 +796,7 @@ bool Instance::Private::rpcErrorOccured(mtpRequestId requestId, const RPCFailHan
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Instance::Private::hasAuthorization() {
|
bool Instance::Private::hasAuthorization() {
|
||||||
return (AuthSession::Current() != nullptr);
|
return AuthSession::Exists();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Instance::Private::importDone(const MTPauth_Authorization &result, mtpRequestId requestId) {
|
void Instance::Private::importDone(const MTPauth_Authorization &result, mtpRequestId requestId) {
|
||||||
|
|
|
@ -42,6 +42,8 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||||
#include "history/history_service_layout.h"
|
#include "history/history_service_layout.h"
|
||||||
#include "media/media_audio.h"
|
#include "media/media_audio.h"
|
||||||
#include "observer_peer.h"
|
#include "observer_peer.h"
|
||||||
|
#include "auth_session.h"
|
||||||
|
#include "storage/file_download.h"
|
||||||
|
|
||||||
// flick scroll taken from http://qt-project.org/doc/qt-4.8/demos-embedded-anomaly-src-flickcharm-cpp.html
|
// flick scroll taken from http://qt-project.org/doc/qt-4.8/demos-embedded-anomaly-src-flickcharm-cpp.html
|
||||||
|
|
||||||
|
@ -59,7 +61,7 @@ OverviewInner::OverviewInner(OverviewWidget *overview, Ui::ScrollArea *scroll, P
|
||||||
, _cancelSearch(this, st::dialogsCancelSearch)
|
, _cancelSearch(this, st::dialogsCancelSearch)
|
||||||
, _itemsToBeLoaded(LinksOverviewPerPage * 2)
|
, _itemsToBeLoaded(LinksOverviewPerPage * 2)
|
||||||
, _width(st::windowMinWidth) {
|
, _width(st::windowMinWidth) {
|
||||||
subscribe(FileDownload::ImageLoaded(), [this] { update(); });
|
subscribe(AuthSession::Current().downloader()->taskFinished(), [this] { update(); });
|
||||||
subscribe(Global::RefItemRemoved(), [this](HistoryItem *item) {
|
subscribe(Global::RefItemRemoved(), [this](HistoryItem *item) {
|
||||||
itemRemoved(item);
|
itemRemoved(item);
|
||||||
});
|
});
|
||||||
|
@ -1917,7 +1919,7 @@ void OverviewWidget::clear() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void OverviewWidget::onScroll() {
|
void OverviewWidget::onScroll() {
|
||||||
MTP::clearLoaderPriorities();
|
AuthSession::Current().downloader()->clearPriorities();
|
||||||
int32 preloadThreshold = _scroll->height() * 5;
|
int32 preloadThreshold = _scroll->height() * 5;
|
||||||
bool needToPreload = false;
|
bool needToPreload = false;
|
||||||
do {
|
do {
|
||||||
|
|
|
@ -72,7 +72,7 @@ void PasscodeWidget::onSubmit() {
|
||||||
cSetPasscodeBadTries(0);
|
cSetPasscodeBadTries(0);
|
||||||
|
|
||||||
Messenger::Instance().startMtp();
|
Messenger::Instance().startMtp();
|
||||||
if (AuthSession::Current()) {
|
if (AuthSession::Exists()) {
|
||||||
App::wnd()->setupMain();
|
App::wnd()->setupMain();
|
||||||
} else {
|
} else {
|
||||||
App::wnd()->setupIntro();
|
App::wnd()->setupIntro();
|
||||||
|
|
|
@ -164,8 +164,10 @@ static gboolean _trayIconCheck(gpointer/* pIn*/) {
|
||||||
if (Libs::gtk_status_icon_is_embedded(_trayIcon)) {
|
if (Libs::gtk_status_icon_is_embedded(_trayIcon)) {
|
||||||
trayIconChecked = true;
|
trayIconChecked = true;
|
||||||
cSetSupportTray(true);
|
cSetSupportTray(true);
|
||||||
|
if (Global::started()) {
|
||||||
|
Global::RefWorkMode().setForced(Global::WorkMode().value(), true);
|
||||||
|
}
|
||||||
if (App::wnd()) {
|
if (App::wnd()) {
|
||||||
App::wnd()->psUpdateWorkmode();
|
|
||||||
Notify::unreadCounterUpdated();
|
Notify::unreadCounterUpdated();
|
||||||
App::wnd()->updateTrayMenu();
|
App::wnd()->updateTrayMenu();
|
||||||
}
|
}
|
||||||
|
@ -196,7 +198,7 @@ void MainWindow::initHook() {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MainWindow::hasTrayIcon() const {
|
bool MainWindow::hasTrayIcon() const {
|
||||||
return trayIcon || ((useAppIndicator || (useStatusIcon && trayIconChecked)) && (cWorkMode() != dbiwmWindowOnly));
|
return trayIcon || ((useAppIndicator || (useStatusIcon && trayIconChecked)) && (Global::WorkMode().value() != dbiwmWindowOnly));
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::psStatusIconCheck() {
|
void MainWindow::psStatusIconCheck() {
|
||||||
|
@ -272,10 +274,10 @@ void MainWindow::psSetupTrayIcon() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::psUpdateWorkmode() {
|
void MainWindow::workmodeUpdated(DBIWorkMode mode) {
|
||||||
if (!cSupportTray()) return;
|
if (!cSupportTray()) return;
|
||||||
|
|
||||||
if (cWorkMode() == dbiwmWindowOnly) {
|
if (mode == dbiwmWindowOnly) {
|
||||||
if (noQtTrayIcon) {
|
if (noQtTrayIcon) {
|
||||||
if (useAppIndicator) {
|
if (useAppIndicator) {
|
||||||
Libs::app_indicator_set_status(_trayIndicator, APP_INDICATOR_STATUS_PASSIVE);
|
Libs::app_indicator_set_status(_trayIndicator, APP_INDICATOR_STATUS_PASSIVE);
|
||||||
|
@ -372,10 +374,6 @@ void MainWindow::updateIconCounters() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MainWindow::psHasNativeNotifications() {
|
|
||||||
return Notifications::Supported();
|
|
||||||
}
|
|
||||||
|
|
||||||
void MainWindow::LibsLoaded() {
|
void MainWindow::LibsLoaded() {
|
||||||
noQtTrayIcon = !DesktopEnvironment::TryQtTrayIcon();
|
noQtTrayIcon = !DesktopEnvironment::TryQtTrayIcon();
|
||||||
tryAppIndicator = !DesktopEnvironment::PreferAppIndicatorTrayIcon();
|
tryAppIndicator = !DesktopEnvironment::PreferAppIndicatorTrayIcon();
|
||||||
|
@ -518,7 +516,7 @@ void MainWindow::psCreateTrayIcon() {
|
||||||
Libs::g_idle_add((GSourceFunc)_trayIconCheck, 0);
|
Libs::g_idle_add((GSourceFunc)_trayIconCheck, 0);
|
||||||
_psCheckStatusIconTimer.start(100);
|
_psCheckStatusIconTimer.start(100);
|
||||||
} else {
|
} else {
|
||||||
psUpdateWorkmode();
|
workmodeUpdated(Global::WorkMode().value());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -555,7 +553,7 @@ void MainWindow::psFirstShow() {
|
||||||
|
|
||||||
if ((cLaunchMode() == LaunchModeAutoStart && cStartMinimized()) || cStartInTray()) {
|
if ((cLaunchMode() == LaunchModeAutoStart && cStartMinimized()) || cStartInTray()) {
|
||||||
setWindowState(Qt::WindowMinimized);
|
setWindowState(Qt::WindowMinimized);
|
||||||
if (cWorkMode() == dbiwmTrayOnly || cWorkMode() == dbiwmWindowAndTray) {
|
if (Global::WorkMode().value() == dbiwmTrayOnly || Global::WorkMode().value() == dbiwmWindowAndTray) {
|
||||||
hide();
|
hide();
|
||||||
} else {
|
} else {
|
||||||
show();
|
show();
|
||||||
|
@ -577,9 +575,6 @@ void MainWindow::psUpdateSysMenu(Qt::WindowState state) {
|
||||||
void MainWindow::psUpdateMargins() {
|
void MainWindow::psUpdateMargins() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::psFlash() {
|
|
||||||
}
|
|
||||||
|
|
||||||
MainWindow::~MainWindow() {
|
MainWindow::~MainWindow() {
|
||||||
if (_trayIcon) {
|
if (_trayIcon) {
|
||||||
Libs::g_object_unref(_trayIcon);
|
Libs::g_object_unref(_trayIcon);
|
||||||
|
|
|
@ -35,16 +35,9 @@ public:
|
||||||
void psUpdateSysMenu(Qt::WindowState state);
|
void psUpdateSysMenu(Qt::WindowState state);
|
||||||
void psUpdateMargins();
|
void psUpdateMargins();
|
||||||
|
|
||||||
void psFlash();
|
|
||||||
void psNotifySettingGot();
|
|
||||||
|
|
||||||
void psUpdateWorkmode();
|
|
||||||
|
|
||||||
void psRefreshTaskbarIcon() {
|
void psRefreshTaskbarIcon() {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool psHasNativeNotifications();
|
|
||||||
|
|
||||||
virtual QImage iconWithCounter(int size, int count, style::color bg, style::color fg, bool smallIcon) = 0;
|
virtual QImage iconWithCounter(int size, int count, style::color bg, style::color fg, bool smallIcon) = 0;
|
||||||
|
|
||||||
static void LibsLoaded();
|
static void LibsLoaded();
|
||||||
|
@ -63,6 +56,8 @@ protected:
|
||||||
|
|
||||||
bool hasTrayIcon() const override;
|
bool hasTrayIcon() const override;
|
||||||
|
|
||||||
|
void workmodeUpdated(DBIWorkMode mode) override;
|
||||||
|
|
||||||
QSystemTrayIcon *trayIcon = nullptr;
|
QSystemTrayIcon *trayIcon = nullptr;
|
||||||
QMenu *trayIconMenu = nullptr;
|
QMenu *trayIconMenu = nullptr;
|
||||||
QImage icon256, iconbig256;
|
QImage icon256, iconbig256;
|
||||||
|
|
|
@ -24,13 +24,12 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||||
#include "platform/linux/linux_libnotify.h"
|
#include "platform/linux/linux_libnotify.h"
|
||||||
#include "platform/linux/linux_libs.h"
|
#include "platform/linux/linux_libs.h"
|
||||||
#include "lang.h"
|
#include "lang.h"
|
||||||
|
#include "core/task_queue.h"
|
||||||
|
|
||||||
namespace Platform {
|
namespace Platform {
|
||||||
namespace Notifications {
|
namespace Notifications {
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
NeverFreedPointer<Manager> ManagerInstance;
|
|
||||||
|
|
||||||
bool LibNotifyLoaded() {
|
bool LibNotifyLoaded() {
|
||||||
return (Libs::notify_init != nullptr)
|
return (Libs::notify_init != nullptr)
|
||||||
&& (Libs::notify_uninit != nullptr)
|
&& (Libs::notify_uninit != nullptr)
|
||||||
|
@ -100,10 +99,10 @@ QString escapeHtml(const QString &text) {
|
||||||
|
|
||||||
class NotificationData {
|
class NotificationData {
|
||||||
public:
|
public:
|
||||||
NotificationData(const QString &title, const QString &body, const QStringList &capabilities, PeerId peerId, MsgId msgId)
|
NotificationData(const std::shared_ptr<Manager*> &guarded, const QString &title, const QString &body, const QStringList &capabilities, PeerId peerId, MsgId msgId)
|
||||||
: _data(Libs::notify_notification_new(title.toUtf8().constData(), body.toUtf8().constData(), nullptr)) {
|
: _data(Libs::notify_notification_new(title.toUtf8().constData(), body.toUtf8().constData(), nullptr)) {
|
||||||
if (valid()) {
|
if (valid()) {
|
||||||
init(capabilities, peerId, msgId);
|
init(guarded, capabilities, peerId, msgId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
bool valid() const {
|
bool valid() const {
|
||||||
|
@ -158,7 +157,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void init(const QStringList &capabilities, PeerId peerId, MsgId msgId) {
|
void init(const std::shared_ptr<Manager*> &guarded, const QStringList &capabilities, PeerId peerId, MsgId msgId) {
|
||||||
if (capabilities.contains(qsl("append"))) {
|
if (capabilities.contains(qsl("append"))) {
|
||||||
Libs::notify_notification_set_hint_string(_data, "append", "true");
|
Libs::notify_notification_set_hint_string(_data, "append", "true");
|
||||||
} else if (capabilities.contains(qsl("x-canonical-append"))) {
|
} else if (capabilities.contains(qsl("x-canonical-append"))) {
|
||||||
|
@ -169,22 +168,20 @@ private:
|
||||||
auto signalHandler = G_CALLBACK(NotificationData::notificationClosed);
|
auto signalHandler = G_CALLBACK(NotificationData::notificationClosed);
|
||||||
auto signalName = "closed";
|
auto signalName = "closed";
|
||||||
auto signalDataFreeMethod = &NotificationData::notificationDataFreeClosure;
|
auto signalDataFreeMethod = &NotificationData::notificationDataFreeClosure;
|
||||||
auto signalData = new NotificationDataStruct(peerId, msgId);
|
auto signalData = new NotificationDataStruct(guarded, peerId, msgId);
|
||||||
_handlerId = Libs::g_signal_connect_helper(signalReceiver, signalName, signalHandler, signalData, signalDataFreeMethod);
|
_handlerId = Libs::g_signal_connect_helper(signalReceiver, signalName, signalHandler, signalData, signalDataFreeMethod);
|
||||||
|
|
||||||
Libs::notify_notification_set_timeout(_data, Libs::NOTIFY_EXPIRES_DEFAULT);
|
Libs::notify_notification_set_timeout(_data, Libs::NOTIFY_EXPIRES_DEFAULT);
|
||||||
|
|
||||||
if (auto manager = ManagerInstance.data()) {
|
if ((*guarded)->hasActionsSupport()) {
|
||||||
if (manager->hasActionsSupport()) {
|
auto label = lang(lng_notification_reply).toUtf8();
|
||||||
auto label = lang(lng_notification_reply).toUtf8();
|
auto actionReceiver = _data;
|
||||||
auto actionReceiver = _data;
|
auto actionHandler = &NotificationData::notificationClicked;
|
||||||
auto actionHandler = &NotificationData::notificationClicked;
|
auto actionLabel = label.constData();
|
||||||
auto actionLabel = label.constData();
|
auto actionName = "default";
|
||||||
auto actionName = "default";
|
auto actionDataFreeMethod = &NotificationData::notificationDataFree;
|
||||||
auto actionDataFreeMethod = &NotificationData::notificationDataFree;
|
auto actionData = new NotificationDataStruct(guarded, peerId, msgId);
|
||||||
auto actionData = new NotificationDataStruct(peerId, msgId);
|
Libs::notify_notification_add_action(actionReceiver, actionName, actionLabel, actionHandler, actionData, actionDataFreeMethod);
|
||||||
Libs::notify_notification_add_action(actionReceiver, actionName, actionLabel, actionHandler, actionData, actionDataFreeMethod);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -194,12 +191,23 @@ private:
|
||||||
}
|
}
|
||||||
|
|
||||||
struct NotificationDataStruct {
|
struct NotificationDataStruct {
|
||||||
NotificationDataStruct(PeerId peerId, MsgId msgId) : peerId(peerId), msgId(msgId) {
|
NotificationDataStruct(const std::shared_ptr<Manager*> &guarded, PeerId peerId, MsgId msgId)
|
||||||
|
: weak(guarded)
|
||||||
|
, peerId(peerId)
|
||||||
|
, msgId(msgId) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::weak_ptr<Manager*> weak;
|
||||||
PeerId peerId = 0;
|
PeerId peerId = 0;
|
||||||
MsgId msgId = 0;
|
MsgId msgId = 0;
|
||||||
};
|
};
|
||||||
|
static void performOnMainQueue(NotificationDataStruct *data, base::lambda_once<void(Manager *manager)> task) {
|
||||||
|
base::TaskQueue::Main().Put([weak = data->weak, task = std::move(task)]() mutable {
|
||||||
|
if (auto strong = weak.lock()) {
|
||||||
|
task(*strong);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
static void notificationDataFree(gpointer data) {
|
static void notificationDataFree(gpointer data) {
|
||||||
auto notificationData = static_cast<NotificationDataStruct*>(data);
|
auto notificationData = static_cast<NotificationDataStruct*>(data);
|
||||||
delete notificationData;
|
delete notificationData;
|
||||||
|
@ -211,15 +219,15 @@ private:
|
||||||
static void notificationClosed(Libs::NotifyNotification *notification, gpointer data) {
|
static void notificationClosed(Libs::NotifyNotification *notification, gpointer data) {
|
||||||
auto closedReason = Libs::notify_notification_get_closed_reason(notification);
|
auto closedReason = Libs::notify_notification_get_closed_reason(notification);
|
||||||
auto notificationData = static_cast<NotificationDataStruct*>(data);
|
auto notificationData = static_cast<NotificationDataStruct*>(data);
|
||||||
if (auto manager = ManagerInstance.data()) {
|
performOnMainQueue(notificationData, [peerId = notificationData->peerId, msgId = notificationData->msgId](Manager *manager) {
|
||||||
manager->clearNotification(notificationData->peerId, notificationData->msgId);
|
manager->clearNotification(peerId, msgId);
|
||||||
}
|
});
|
||||||
}
|
}
|
||||||
static void notificationClicked(Libs::NotifyNotification *notification, char *action, gpointer data) {
|
static void notificationClicked(Libs::NotifyNotification *notification, char *action, gpointer data) {
|
||||||
auto notificationData = static_cast<NotificationDataStruct*>(data);
|
auto notificationData = static_cast<NotificationDataStruct*>(data);
|
||||||
if (auto manager = ManagerInstance.data()) {
|
performOnMainQueue(notificationData, [peerId = notificationData->peerId, msgId = notificationData->msgId](Manager *manager) {
|
||||||
manager->notificationActivated(notificationData->peerId, notificationData->msgId);
|
manager->notificationActivated(peerId, msgId);
|
||||||
}
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
Libs::NotifyNotification *_data = nullptr;
|
Libs::NotifyNotification *_data = nullptr;
|
||||||
|
@ -229,47 +237,72 @@ private:
|
||||||
|
|
||||||
using Notification = QSharedPointer<NotificationData>;
|
using Notification = QSharedPointer<NotificationData>;
|
||||||
|
|
||||||
} // namespace
|
QString GetServerName() {
|
||||||
|
if (!LibNotifyLoaded()) {
|
||||||
void Start() {
|
return QString();
|
||||||
if (LibNotifyLoaded()) {
|
|
||||||
if (Libs::notify_is_initted() || Libs::notify_init("Telegram Desktop")) {
|
|
||||||
ManagerInstance.createIfNull();
|
|
||||||
if (!ManagerInstance->init()) {
|
|
||||||
ManagerInstance.clear();
|
|
||||||
LOG(("LibNotify Error: manager failed to init!"));
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
LOG(("LibNotify Error: failed to init!"));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
if (!Libs::notify_is_initted() && !Libs::notify_init("Telegram Desktop")) {
|
||||||
|
LOG(("LibNotify Error: failed to init!"));
|
||||||
|
return QString();
|
||||||
|
}
|
||||||
|
|
||||||
|
gchar *name = nullptr;
|
||||||
|
auto guard = base::scope_guard([&name] {
|
||||||
|
if (name) Libs::g_free(name);
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!Libs::notify_get_server_info(&name, nullptr, nullptr, nullptr)) {
|
||||||
|
LOG(("LibNotify Error: could not get server name!"));
|
||||||
|
return QString();
|
||||||
|
}
|
||||||
|
if (!name) {
|
||||||
|
LOG(("LibNotify Error: successfully got empty server name!"));
|
||||||
|
return QString();
|
||||||
|
}
|
||||||
|
|
||||||
|
auto result = QString::fromUtf8(static_cast<const char*>(name));
|
||||||
|
LOG(("Notifications Server: %1").arg(result));
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
Window::Notifications::Manager *GetManager() {
|
auto LibNotifyServerName = QString();
|
||||||
if (Global::started() && Global::NativeNotifications()) {
|
|
||||||
return ManagerInstance.data();
|
} // namespace
|
||||||
|
|
||||||
|
bool Supported() {
|
||||||
|
static auto Checked = false;
|
||||||
|
if (!Checked) {
|
||||||
|
Checked = true;
|
||||||
|
LibNotifyServerName = GetServerName();
|
||||||
|
}
|
||||||
|
|
||||||
|
return !LibNotifyServerName.isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<Window::Notifications::Manager> Create(Window::Notifications::System *system) {
|
||||||
|
if (Global::NativeNotifications() && Supported()) {
|
||||||
|
return std::make_unique<Manager>(system);
|
||||||
}
|
}
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Supported() {
|
|
||||||
return ManagerInstance.data() != nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Finish() {
|
void Finish() {
|
||||||
if (GetManager()) {
|
if (Libs::notify_is_initted && Libs::notify_uninit) {
|
||||||
ManagerInstance.reset();
|
if (Libs::notify_is_initted()) {
|
||||||
Libs::notify_uninit();
|
Libs::notify_uninit();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class Manager::Impl {
|
class Manager::Private {
|
||||||
public:
|
public:
|
||||||
using Type = Window::Notifications::CachedUserpics::Type;
|
using Type = Window::Notifications::CachedUserpics::Type;
|
||||||
Impl(Type type) : _cachedUserpics(type) {
|
explicit Private(Type type)
|
||||||
|
: _cachedUserpics(type) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool init();
|
void init(Manager *manager);
|
||||||
|
|
||||||
void showNotification(PeerData *peer, MsgId msgId, const QString &title, const QString &subtitle, const QString &msg, bool hideNameAndPhoto, bool hideReplyButton);
|
void showNotification(PeerData *peer, MsgId msgId, const QString &title, const QString &subtitle, const QString &msg, bool hideNameAndPhoto, bool hideReplyButton);
|
||||||
void clearAll();
|
void clearAll();
|
||||||
|
@ -283,6 +316,8 @@ public:
|
||||||
return _actionsSupported;
|
return _actionsSupported;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
~Private();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QString escapeNotificationText(const QString &text) const;
|
QString escapeNotificationText(const QString &text) const;
|
||||||
void showNextNotification();
|
void showNextNotification();
|
||||||
|
@ -309,9 +344,13 @@ private:
|
||||||
bool _markupSupported = false;
|
bool _markupSupported = false;
|
||||||
bool _poorSupported = false;
|
bool _poorSupported = false;
|
||||||
|
|
||||||
|
std::shared_ptr<Manager*> _guarded;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
bool Manager::Impl::init() {
|
void Manager::Private::init(Manager *manager) {
|
||||||
|
_guarded = std::make_shared<Manager*>(manager);
|
||||||
|
|
||||||
if (auto capabilities = Libs::notify_get_server_caps()) {
|
if (auto capabilities = Libs::notify_get_server_caps()) {
|
||||||
for (auto capability = capabilities; capability; capability = capability->next) {
|
for (auto capability = capabilities; capability; capability = capability->next) {
|
||||||
auto capabilityText = QString::fromUtf8(static_cast<const char*>(capability->data));
|
auto capabilityText = QString::fromUtf8(static_cast<const char*>(capability->data));
|
||||||
|
@ -331,32 +370,19 @@ bool Manager::Impl::init() {
|
||||||
|
|
||||||
// Unity and other Notify OSD users handle desktop notifications
|
// Unity and other Notify OSD users handle desktop notifications
|
||||||
// extremely poor, even without the ability to close() them.
|
// extremely poor, even without the ability to close() them.
|
||||||
gchar *name = nullptr;
|
_serverName = LibNotifyServerName;
|
||||||
if (Libs::notify_get_server_info(&name, nullptr, nullptr, nullptr)) {
|
t_assert(!_serverName.isEmpty());
|
||||||
if (name) {
|
if (_serverName == qstr("notify-osd")) {
|
||||||
_serverName = QString::fromUtf8(static_cast<const char*>(name));
|
// _poorSupported = true;
|
||||||
Libs::g_free(name);
|
_actionsSupported = false;
|
||||||
|
|
||||||
LOG(("Notifications Server: %1").arg(_serverName));
|
|
||||||
if (_serverName == qstr("notify-osd")) {
|
|
||||||
// _poorSupported = true;
|
|
||||||
_actionsSupported = false;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
LOG(("LibNotify Error: successfully got empty server name!"));
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
LOG(("LibNotify Error: could not get server name!"));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return !_serverName.isEmpty();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QString Manager::Impl::escapeNotificationText(const QString &text) const {
|
QString Manager::Private::escapeNotificationText(const QString &text) const {
|
||||||
return _markupSupported ? escapeHtml(text) : text;
|
return _markupSupported ? escapeHtml(text) : text;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Manager::Impl::showNotification(PeerData *peer, MsgId msgId, const QString &title, const QString &subtitle, const QString &msg, bool hideNameAndPhoto, bool hideReplyButton) {
|
void Manager::Private::showNotification(PeerData *peer, MsgId msgId, const QString &title, const QString &subtitle, const QString &msg, bool hideNameAndPhoto, bool hideReplyButton) {
|
||||||
auto titleText = escapeNotificationText(title);
|
auto titleText = escapeNotificationText(title);
|
||||||
auto subtitleText = escapeNotificationText(subtitle);
|
auto subtitleText = escapeNotificationText(subtitle);
|
||||||
auto msgText = escapeNotificationText(msg);
|
auto msgText = escapeNotificationText(msg);
|
||||||
|
@ -376,7 +402,7 @@ void Manager::Impl::showNotification(PeerData *peer, MsgId msgId, const QString
|
||||||
showNextNotification();
|
showNextNotification();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Manager::Impl::showNextNotification() {
|
void Manager::Private::showNextNotification() {
|
||||||
// Show only one notification at a time in Unity / Notify OSD.
|
// Show only one notification at a time in Unity / Notify OSD.
|
||||||
if (_poorSupported) {
|
if (_poorSupported) {
|
||||||
for (auto b = _notifications.begin(); !_notifications.isEmpty() && b->isEmpty();) {
|
for (auto b = _notifications.begin(); !_notifications.isEmpty() && b->isEmpty();) {
|
||||||
|
@ -401,7 +427,7 @@ void Manager::Impl::showNextNotification() {
|
||||||
|
|
||||||
auto peerId = data.peer->id;
|
auto peerId = data.peer->id;
|
||||||
auto msgId = data.msgId;
|
auto msgId = data.msgId;
|
||||||
auto notification = MakeShared<NotificationData>(data.title, data.body, _capabilities, peerId, msgId);
|
auto notification = MakeShared<NotificationData>(_guarded, data.title, data.body, _capabilities, peerId, msgId);
|
||||||
if (!notification->valid()) {
|
if (!notification->valid()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -438,7 +464,7 @@ void Manager::Impl::showNextNotification() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Manager::Impl::clearAll() {
|
void Manager::Private::clearAll() {
|
||||||
_queuedNotifications.clear();
|
_queuedNotifications.clear();
|
||||||
|
|
||||||
auto temp = base::take(_notifications);
|
auto temp = base::take(_notifications);
|
||||||
|
@ -449,7 +475,7 @@ void Manager::Impl::clearAll() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Manager::Impl::clearFromHistory(History *history) {
|
void Manager::Private::clearFromHistory(History *history) {
|
||||||
for (auto i = _queuedNotifications.begin(); i != _queuedNotifications.end();) {
|
for (auto i = _queuedNotifications.begin(); i != _queuedNotifications.end();) {
|
||||||
if (i->peer == history->peer) {
|
if (i->peer == history->peer) {
|
||||||
i = _queuedNotifications.erase(i);
|
i = _queuedNotifications.erase(i);
|
||||||
|
@ -471,7 +497,7 @@ void Manager::Impl::clearFromHistory(History *history) {
|
||||||
showNextNotification();
|
showNextNotification();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Manager::Impl::clearNotification(PeerId peerId, MsgId msgId) {
|
void Manager::Private::clearNotification(PeerId peerId, MsgId msgId) {
|
||||||
auto i = _notifications.find(peerId);
|
auto i = _notifications.find(peerId);
|
||||||
if (i != _notifications.cend()) {
|
if (i != _notifications.cend()) {
|
||||||
i.value().remove(msgId);
|
i.value().remove(msgId);
|
||||||
|
@ -483,37 +509,39 @@ void Manager::Impl::clearNotification(PeerId peerId, MsgId msgId) {
|
||||||
showNextNotification();
|
showNextNotification();
|
||||||
}
|
}
|
||||||
|
|
||||||
Manager::Manager() : _impl(std::make_unique<Impl>(Impl::Type::Rounded)) {
|
Manager::Private::~Private() {
|
||||||
|
clearAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Manager::init() {
|
Manager::Manager(Window::Notifications::System *system) : NativeManager(system)
|
||||||
return _impl->init();
|
, _private(std::make_unique<Private>(Private::Type::Rounded)) {
|
||||||
|
_private->init(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Manager::clearNotification(PeerId peerId, MsgId msgId) {
|
void Manager::clearNotification(PeerId peerId, MsgId msgId) {
|
||||||
_impl->clearNotification(peerId, msgId);
|
_private->clearNotification(peerId, msgId);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Manager::hasPoorSupport() const {
|
bool Manager::hasPoorSupport() const {
|
||||||
return _impl->hasPoorSupport();
|
return _private->hasPoorSupport();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Manager::hasActionsSupport() const {
|
bool Manager::hasActionsSupport() const {
|
||||||
return _impl->hasActionsSupport();
|
return _private->hasActionsSupport();
|
||||||
}
|
}
|
||||||
|
|
||||||
Manager::~Manager() = default;
|
Manager::~Manager() = default;
|
||||||
|
|
||||||
void Manager::doShowNativeNotification(PeerData *peer, MsgId msgId, const QString &title, const QString &subtitle, const QString &msg, bool hideNameAndPhoto, bool hideReplyButton) {
|
void Manager::doShowNativeNotification(PeerData *peer, MsgId msgId, const QString &title, const QString &subtitle, const QString &msg, bool hideNameAndPhoto, bool hideReplyButton) {
|
||||||
_impl->showNotification(peer, msgId, title, subtitle, msg, hideNameAndPhoto, hideReplyButton);
|
_private->showNotification(peer, msgId, title, subtitle, msg, hideNameAndPhoto, hideReplyButton);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Manager::doClearAllFast() {
|
void Manager::doClearAllFast() {
|
||||||
_impl->clearAll();
|
_private->clearAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Manager::doClearFromHistory(History *history) {
|
void Manager::doClearFromHistory(History *history) {
|
||||||
_impl->clearFromHistory(history);
|
_private->clearFromHistory(history);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Notifications
|
} // namespace Notifications
|
||||||
|
|
|
@ -36,11 +36,14 @@ inline bool SkipToast() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline void FlashBounce() {
|
||||||
|
}
|
||||||
|
|
||||||
|
void Finish();
|
||||||
|
|
||||||
class Manager : public Window::Notifications::NativeManager {
|
class Manager : public Window::Notifications::NativeManager {
|
||||||
public:
|
public:
|
||||||
Manager();
|
Manager(Window::Notifications::System *system);
|
||||||
|
|
||||||
bool init();
|
|
||||||
|
|
||||||
void clearNotification(PeerId peerId, MsgId msgId);
|
void clearNotification(PeerId peerId, MsgId msgId);
|
||||||
bool hasPoorSupport() const;
|
bool hasPoorSupport() const;
|
||||||
|
@ -54,9 +57,8 @@ protected:
|
||||||
void doClearFromHistory(History *history) override;
|
void doClearFromHistory(History *history) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
class Impl;
|
class Private;
|
||||||
friend class Impl;
|
const std::unique_ptr<Private> _private;
|
||||||
std::unique_ptr<Impl> _impl;
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -23,6 +23,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||||
#include "mainwidget.h"
|
#include "mainwidget.h"
|
||||||
#include "mainwindow.h"
|
#include "mainwindow.h"
|
||||||
#include "platform/linux/file_utilities_linux.h"
|
#include "platform/linux/file_utilities_linux.h"
|
||||||
|
#include "platform/platform_notifications_manager.h"
|
||||||
#include "storage/localstorage.h"
|
#include "storage/localstorage.h"
|
||||||
|
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
@ -370,6 +371,8 @@ void start() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void finish() {
|
void finish() {
|
||||||
|
Notifications::Finish();
|
||||||
|
|
||||||
delete _psEventFilter;
|
delete _psEventFilter;
|
||||||
_psEventFilter = nullptr;
|
_psEventFilter = nullptr;
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,25 +36,20 @@ public:
|
||||||
void psUpdateSysMenu(Qt::WindowState state);
|
void psUpdateSysMenu(Qt::WindowState state);
|
||||||
void psUpdateMargins();
|
void psUpdateMargins();
|
||||||
|
|
||||||
void psFlash();
|
|
||||||
|
|
||||||
void psUpdateWorkmode();
|
|
||||||
|
|
||||||
void psRefreshTaskbarIcon() {
|
void psRefreshTaskbarIcon() {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool psFilterNativeEvent(void *event);
|
bool psFilterNativeEvent(void *event);
|
||||||
|
|
||||||
bool psHasNativeNotifications() {
|
|
||||||
return !(QSysInfo::macVersion() < QSysInfo::MV_10_8);
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual QImage iconWithCounter(int size, int count, style::color bg, style::color fg, bool smallIcon) = 0;
|
virtual QImage iconWithCounter(int size, int count, style::color bg, style::color fg, bool smallIcon) = 0;
|
||||||
|
|
||||||
int getCustomTitleHeight() const {
|
int getCustomTitleHeight() const {
|
||||||
return _customTitleHeight;
|
return _customTitleHeight;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// It is placed here while the window handles activeSpaceDidChange event.
|
||||||
|
void customNotificationCreated(QWidget *notification);
|
||||||
|
|
||||||
~MainWindow();
|
~MainWindow();
|
||||||
|
|
||||||
class Private;
|
class Private;
|
||||||
|
@ -88,6 +83,8 @@ protected:
|
||||||
|
|
||||||
void updateGlobalMenuHook() override;
|
void updateGlobalMenuHook() override;
|
||||||
|
|
||||||
|
void workmodeUpdated(DBIWorkMode mode) override;
|
||||||
|
|
||||||
QSystemTrayIcon *trayIcon = nullptr;
|
QSystemTrayIcon *trayIcon = nullptr;
|
||||||
QMenu *trayIconMenu = nullptr;
|
QMenu *trayIconMenu = nullptr;
|
||||||
QImage icon256, iconbig256;
|
QImage icon256, iconbig256;
|
||||||
|
@ -109,9 +106,16 @@ private:
|
||||||
void updateTitleCounter();
|
void updateTitleCounter();
|
||||||
void updateIconCounters();
|
void updateIconCounters();
|
||||||
|
|
||||||
|
class CustomNotificationHandle;
|
||||||
|
friend class CustomNotificationHandle;
|
||||||
|
void customNotificationDestroyed(CustomNotificationHandle *handle);
|
||||||
|
void activateCustomNotifications();
|
||||||
|
|
||||||
friend class Private;
|
friend class Private;
|
||||||
std::unique_ptr<Private> _private;
|
std::unique_ptr<Private> _private;
|
||||||
|
|
||||||
|
std::set<CustomNotificationHandle*> _customNotifications;
|
||||||
|
|
||||||
mutable bool psIdle;
|
mutable bool psIdle;
|
||||||
mutable QTimer psIdleTimer;
|
mutable QTimer psIdleTimer;
|
||||||
|
|
||||||
|
|
|
@ -56,7 +56,6 @@ public:
|
||||||
Private(MainWindow *window);
|
Private(MainWindow *window);
|
||||||
|
|
||||||
void setWindowBadge(const QString &str);
|
void setWindowBadge(const QString &str);
|
||||||
void startBounce();
|
|
||||||
|
|
||||||
void enableShadow(WId winId);
|
void enableShadow(WId winId);
|
||||||
|
|
||||||
|
@ -64,6 +63,7 @@ public:
|
||||||
|
|
||||||
void willEnterFullScreen();
|
void willEnterFullScreen();
|
||||||
void willExitFullScreen();
|
void willExitFullScreen();
|
||||||
|
void activateCustomNotifications();
|
||||||
|
|
||||||
void initCustomTitle(NSWindow *window, NSView *view);
|
void initCustomTitle(NSWindow *window, NSView *view);
|
||||||
|
|
||||||
|
@ -82,6 +82,25 @@ private:
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class MainWindow::CustomNotificationHandle : public QObject {
|
||||||
|
public:
|
||||||
|
CustomNotificationHandle(QWidget *parent) : QObject(parent) {
|
||||||
|
}
|
||||||
|
|
||||||
|
void activate() {
|
||||||
|
auto widget = static_cast<QWidget*>(parent());
|
||||||
|
NSWindow *wnd = [reinterpret_cast<NSView *>(widget->winId()) window];
|
||||||
|
[wnd orderFront:wnd];
|
||||||
|
}
|
||||||
|
|
||||||
|
~CustomNotificationHandle() {
|
||||||
|
if (auto window = App::wnd()) {
|
||||||
|
window->customNotificationDestroyed(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
} // namespace Platform
|
} // namespace Platform
|
||||||
|
|
||||||
@implementation MainWindowObserver {
|
@implementation MainWindowObserver {
|
||||||
|
@ -98,11 +117,7 @@ MainWindow::Private *_private;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void) activeSpaceDidChange:(NSNotification *)aNotification {
|
- (void) activeSpaceDidChange:(NSNotification *)aNotification {
|
||||||
if (auto manager = Window::Notifications::Default::GetManager()) {
|
_private->activateCustomNotifications();
|
||||||
manager->enumerateNotifications([](QWidget *widget) {
|
|
||||||
objc_activateWnd(widget->winId());
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void) darkModeChanged:(NSNotification *)aNotification {
|
- (void) darkModeChanged:(NSNotification *)aNotification {
|
||||||
|
@ -157,10 +172,6 @@ void MainWindow::Private::setWindowBadge(const QString &str) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::Private::startBounce() {
|
|
||||||
[NSApp requestUserAttention:NSInformationalRequest];
|
|
||||||
}
|
|
||||||
|
|
||||||
void MainWindow::Private::initCustomTitle(NSWindow *window, NSView *view) {
|
void MainWindow::Private::initCustomTitle(NSWindow *window, NSView *view) {
|
||||||
[window setStyleMask:[window styleMask] | NSFullSizeContentViewWindowMask];
|
[window setStyleMask:[window styleMask] | NSFullSizeContentViewWindowMask];
|
||||||
[window setTitlebarAppearsTransparent:YES];
|
[window setTitlebarAppearsTransparent:YES];
|
||||||
|
@ -191,6 +202,10 @@ void MainWindow::Private::willExitFullScreen() {
|
||||||
_public->setTitleVisible(true);
|
_public->setTitleVisible(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MainWindow::Private::activateCustomNotifications() {
|
||||||
|
_public->activateCustomNotifications();
|
||||||
|
}
|
||||||
|
|
||||||
void MainWindow::Private::enableShadow(WId winId) {
|
void MainWindow::Private::enableShadow(WId winId) {
|
||||||
// [[(NSView*)winId window] setStyleMask:NSBorderlessWindowMask];
|
// [[(NSView*)winId window] setStyleMask:NSBorderlessWindowMask];
|
||||||
// [[(NSView*)winId window] setHasShadow:YES];
|
// [[(NSView*)winId window] setHasShadow:YES];
|
||||||
|
@ -299,18 +314,15 @@ void MainWindow::psSetupTrayIcon() {
|
||||||
trayIcon->show();
|
trayIcon->show();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::psUpdateWorkmode() {
|
void MainWindow::workmodeUpdated(DBIWorkMode mode) {
|
||||||
psSetupTrayIcon();
|
psSetupTrayIcon();
|
||||||
if (cWorkMode() == dbiwmWindowOnly) {
|
if (mode == dbiwmWindowOnly) {
|
||||||
if (trayIcon) {
|
if (trayIcon) {
|
||||||
trayIcon->setContextMenu(0);
|
trayIcon->setContextMenu(0);
|
||||||
delete trayIcon;
|
delete trayIcon;
|
||||||
trayIcon = nullptr;
|
trayIcon = nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (auto manager = Platform::Notifications::GetNativeManager()) {
|
|
||||||
manager->updateDelegate();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void _placeCounter(QImage &img, int size, int count, style::color bg, style::color color) {
|
void _placeCounter(QImage &img, int size, int count, style::color bg, style::color color) {
|
||||||
|
@ -400,7 +412,7 @@ void MainWindow::psFirstShow() {
|
||||||
|
|
||||||
if ((cLaunchMode() == LaunchModeAutoStart && cStartMinimized()) || cStartInTray()) {
|
if ((cLaunchMode() == LaunchModeAutoStart && cStartMinimized()) || cStartInTray()) {
|
||||||
setWindowState(Qt::WindowMinimized);
|
setWindowState(Qt::WindowMinimized);
|
||||||
if (cWorkMode() == dbiwmTrayOnly || cWorkMode() == dbiwmWindowAndTray) {
|
if (Global::WorkMode().value() == dbiwmTrayOnly || Global::WorkMode().value() == dbiwmWindowAndTray) {
|
||||||
hide();
|
hide();
|
||||||
} else {
|
} else {
|
||||||
show();
|
show();
|
||||||
|
@ -514,6 +526,20 @@ void MainWindow::psUpdateSysMenu(Qt::WindowState state) {
|
||||||
void MainWindow::psUpdateMargins() {
|
void MainWindow::psUpdateMargins() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MainWindow::customNotificationCreated(QWidget *notification) {
|
||||||
|
_customNotifications.insert(object_ptr<CustomNotificationHandle>(notification));
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::customNotificationDestroyed(CustomNotificationHandle *handle) {
|
||||||
|
_customNotifications.erase(handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::activateCustomNotifications() {
|
||||||
|
for (auto handle : _customNotifications) {
|
||||||
|
handle->activate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void MainWindow::updateGlobalMenuHook() {
|
void MainWindow::updateGlobalMenuHook() {
|
||||||
if (!App::wnd() || !positionInited()) return;
|
if (!App::wnd() || !positionInited()) return;
|
||||||
|
|
||||||
|
@ -552,10 +578,6 @@ void MainWindow::updateGlobalMenuHook() {
|
||||||
_forceDisabled(psShowTelegram, App::wnd()->isActive());
|
_forceDisabled(psShowTelegram, App::wnd()->isActive());
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::psFlash() {
|
|
||||||
return _private->startBounce();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool MainWindow::psFilterNativeEvent(void *event) {
|
bool MainWindow::psFilterNativeEvent(void *event) {
|
||||||
return _private->filterNativeEvent(event);
|
return _private->filterNativeEvent(event);
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,9 +25,6 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||||
namespace Platform {
|
namespace Platform {
|
||||||
namespace Notifications {
|
namespace Notifications {
|
||||||
|
|
||||||
class Manager;
|
|
||||||
Manager *GetNativeManager();
|
|
||||||
|
|
||||||
inline bool SkipAudio() {
|
inline bool SkipAudio() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -38,10 +35,7 @@ inline bool SkipToast() {
|
||||||
|
|
||||||
class Manager : public Window::Notifications::NativeManager {
|
class Manager : public Window::Notifications::NativeManager {
|
||||||
public:
|
public:
|
||||||
Manager();
|
Manager(Window::Notifications::System *system);
|
||||||
|
|
||||||
void updateDelegate();
|
|
||||||
|
|
||||||
~Manager();
|
~Manager();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
@ -50,14 +44,10 @@ protected:
|
||||||
void doClearFromHistory(History *history) override;
|
void doClearFromHistory(History *history) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
class Impl;
|
class Private;
|
||||||
std::unique_ptr<Impl> _impl;
|
const std::unique_ptr<Private> _private;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
inline Window::Notifications::Manager *GetManager() {
|
|
||||||
return GetNativeManager();
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace Notifications
|
} // namespace Notifications
|
||||||
} // namespace Platform
|
} // namespace Platform
|
||||||
|
|
|
@ -23,6 +23,8 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||||
#include "platform/platform_specific.h"
|
#include "platform/platform_specific.h"
|
||||||
#include "platform/mac/mac_utilities.h"
|
#include "platform/mac/mac_utilities.h"
|
||||||
#include "styles/style_window.h"
|
#include "styles/style_window.h"
|
||||||
|
#include "mainwindow.h"
|
||||||
|
#include "core/task_queue.h"
|
||||||
|
|
||||||
#include <Cocoa/Cocoa.h>
|
#include <Cocoa/Cocoa.h>
|
||||||
|
|
||||||
|
@ -93,22 +95,19 @@ NSImage *qt_mac_create_nsimage(const QPixmap &pm);
|
||||||
namespace Platform {
|
namespace Platform {
|
||||||
namespace Notifications {
|
namespace Notifications {
|
||||||
|
|
||||||
void Start() {
|
|
||||||
if (cPlatform() != dbipMacOld) {
|
|
||||||
ManagerInstance.createIfNull();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Manager *GetNativeManager() {
|
|
||||||
return ManagerInstance.data();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Supported() {
|
bool Supported() {
|
||||||
return ManagerInstance.data() != nullptr;
|
return (cPlatform() != dbipMacOld);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Finish() {
|
std::unique_ptr<Window::Notifications::Manager> Create(Window::Notifications::System *system) {
|
||||||
ManagerInstance.clear();
|
if (Supported()) {
|
||||||
|
return std::make_unique<Manager>(system);
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FlashBounce() {
|
||||||
|
[NSApp requestUserAttention:NSInformationalRequest];
|
||||||
}
|
}
|
||||||
|
|
||||||
void CustomNotificationShownHook(QWidget *widget) {
|
void CustomNotificationShownHook(QWidget *widget) {
|
||||||
|
@ -116,27 +115,38 @@ void CustomNotificationShownHook(QWidget *widget) {
|
||||||
objc_holdOnTop(widget->winId());
|
objc_holdOnTop(widget->winId());
|
||||||
widget->show();
|
widget->show();
|
||||||
psShowOverAll(widget, false);
|
psShowOverAll(widget, false);
|
||||||
|
if (auto window = App::wnd()) {
|
||||||
|
window->customNotificationCreated(widget);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class Manager::Impl {
|
class Manager::Private : public QObject, private base::Subscriber {
|
||||||
public:
|
public:
|
||||||
Impl();
|
Private();
|
||||||
void showNotification(PeerData *peer, MsgId msgId, const QString &title, const QString &subtitle, const QString &msg, bool hideNameAndPhoto, bool hideReplyButton);
|
void showNotification(PeerData *peer, MsgId msgId, const QString &title, const QString &subtitle, const QString &msg, bool hideNameAndPhoto, bool hideReplyButton);
|
||||||
void clearAll();
|
void clearAll();
|
||||||
void clearFromHistory(History *history);
|
void clearFromHistory(History *history);
|
||||||
void updateDelegate();
|
void updateDelegate();
|
||||||
|
|
||||||
~Impl();
|
~Private();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
NotificationDelegate *_delegate;
|
NotificationDelegate *_delegate;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
Manager::Impl::Impl() : _delegate([[NotificationDelegate alloc] init]) {
|
Manager::Private::Private() : _delegate([[NotificationDelegate alloc] init]) {
|
||||||
|
updateDelegate();
|
||||||
|
subscribe(Global::RefWorkMode(), [this](DBIWorkMode mode) {
|
||||||
|
// We need to update the delegate _after_ the tray icon change was done in Qt.
|
||||||
|
// Because Qt resets the delegate.
|
||||||
|
base::TaskQueue::Main().Put(base::lambda_guarded(this, [this] {
|
||||||
|
updateDelegate();
|
||||||
|
}));
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void Manager::Impl::showNotification(PeerData *peer, MsgId msgId, const QString &title, const QString &subtitle, const QString &msg, bool hideNameAndPhoto, bool hideReplyButton) {
|
void Manager::Private::showNotification(PeerData *peer, MsgId msgId, const QString &title, const QString &subtitle, const QString &msg, bool hideNameAndPhoto, bool hideReplyButton) {
|
||||||
@autoreleasepool {
|
@autoreleasepool {
|
||||||
|
|
||||||
NSUserNotification *notification = [[[NSUserNotification alloc] init] autorelease];
|
NSUserNotification *notification = [[[NSUserNotification alloc] init] autorelease];
|
||||||
|
@ -168,7 +178,7 @@ void Manager::Impl::showNotification(PeerData *peer, MsgId msgId, const QString
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Manager::Impl::clearAll() {
|
void Manager::Private::clearAll() {
|
||||||
NSUserNotificationCenter *center = [NSUserNotificationCenter defaultUserNotificationCenter];
|
NSUserNotificationCenter *center = [NSUserNotificationCenter defaultUserNotificationCenter];
|
||||||
NSArray *notificationsList = [center deliveredNotifications];
|
NSArray *notificationsList = [center deliveredNotifications];
|
||||||
for (id notification in notificationsList) {
|
for (id notification in notificationsList) {
|
||||||
|
@ -182,7 +192,7 @@ void Manager::Impl::clearAll() {
|
||||||
[center removeAllDeliveredNotifications];
|
[center removeAllDeliveredNotifications];
|
||||||
}
|
}
|
||||||
|
|
||||||
void Manager::Impl::clearFromHistory(History *history) {
|
void Manager::Private::clearFromHistory(History *history) {
|
||||||
unsigned long long peerId = history->peer->id;
|
unsigned long long peerId = history->peer->id;
|
||||||
|
|
||||||
NSUserNotificationCenter *center = [NSUserNotificationCenter defaultUserNotificationCenter];
|
NSUserNotificationCenter *center = [NSUserNotificationCenter defaultUserNotificationCenter];
|
||||||
|
@ -199,34 +209,32 @@ void Manager::Impl::clearFromHistory(History *history) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Manager::Impl::updateDelegate() {
|
void Manager::Private::updateDelegate() {
|
||||||
NSUserNotificationCenter *center = [NSUserNotificationCenter defaultUserNotificationCenter];
|
NSUserNotificationCenter *center = [NSUserNotificationCenter defaultUserNotificationCenter];
|
||||||
[center setDelegate:_delegate];
|
[center setDelegate:_delegate];
|
||||||
}
|
}
|
||||||
|
|
||||||
Manager::Impl::~Impl() {
|
Manager::Private::~Private() {
|
||||||
|
clearAll();
|
||||||
[_delegate release];
|
[_delegate release];
|
||||||
}
|
}
|
||||||
|
|
||||||
Manager::Manager() : _impl(std::make_unique<Impl>()) {
|
Manager::Manager(Window::Notifications::System *system) : NativeManager(system)
|
||||||
}
|
, _private(std::make_unique<Private>()) {
|
||||||
|
|
||||||
void Manager::updateDelegate() {
|
|
||||||
_impl->updateDelegate();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Manager::~Manager() = default;
|
Manager::~Manager() = default;
|
||||||
|
|
||||||
void Manager::doShowNativeNotification(PeerData *peer, MsgId msgId, const QString &title, const QString &subtitle, const QString &msg, bool hideNameAndPhoto, bool hideReplyButton) {
|
void Manager::doShowNativeNotification(PeerData *peer, MsgId msgId, const QString &title, const QString &subtitle, const QString &msg, bool hideNameAndPhoto, bool hideReplyButton) {
|
||||||
_impl->showNotification(peer, msgId, title, subtitle, msg, hideNameAndPhoto, hideReplyButton);
|
_private->showNotification(peer, msgId, title, subtitle, msg, hideNameAndPhoto, hideReplyButton);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Manager::doClearAllFast() {
|
void Manager::doClearAllFast() {
|
||||||
_impl->clearAll();
|
_private->clearAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Manager::doClearFromHistory(History *history) {
|
void Manager::doClearFromHistory(History *history) {
|
||||||
_impl->clearFromHistory(history);
|
_private->clearFromHistory(history);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Notifications
|
} // namespace Notifications
|
||||||
|
|
|
@ -24,7 +24,6 @@ void objc_holdOnTop(WId winId);
|
||||||
bool objc_darkMode();
|
bool objc_darkMode();
|
||||||
void objc_showOverAll(WId winId, bool canFocus = true);
|
void objc_showOverAll(WId winId, bool canFocus = true);
|
||||||
void objc_bringToBack(WId winId);
|
void objc_bringToBack(WId winId);
|
||||||
void objc_activateWnd(WId winId);
|
|
||||||
|
|
||||||
void objc_debugShowAlert(const QString &str);
|
void objc_debugShowAlert(const QString &str);
|
||||||
void objc_outputDebugString(const QString &str);
|
void objc_outputDebugString(const QString &str);
|
||||||
|
|
|
@ -208,11 +208,6 @@ void objc_bringToBack(WId winId) {
|
||||||
[wnd setLevel:NSModalPanelWindowLevel];
|
[wnd setLevel:NSModalPanelWindowLevel];
|
||||||
}
|
}
|
||||||
|
|
||||||
void objc_activateWnd(WId winId) {
|
|
||||||
NSWindow *wnd = [reinterpret_cast<NSView *>(winId) window];
|
|
||||||
[wnd orderFront:wnd];
|
|
||||||
}
|
|
||||||
|
|
||||||
bool objc_handleMediaKeyEvent(void *ev) {
|
bool objc_handleMediaKeyEvent(void *ev) {
|
||||||
auto e = reinterpret_cast<NSEvent*>(ev);
|
auto e = reinterpret_cast<NSEvent*>(ev);
|
||||||
|
|
||||||
|
|
|
@ -29,10 +29,9 @@ void CustomNotificationShownHook(QWidget *widget);
|
||||||
bool SkipAudio();
|
bool SkipAudio();
|
||||||
bool SkipToast();
|
bool SkipToast();
|
||||||
|
|
||||||
void Start();
|
|
||||||
Window::Notifications::Manager *GetManager();
|
|
||||||
bool Supported();
|
bool Supported();
|
||||||
void Finish();
|
std::unique_ptr<Window::Notifications::Manager> Create(Window::Notifications::System *system);
|
||||||
|
void FlashBounce();
|
||||||
|
|
||||||
} // namespace Notifications
|
} // namespace Notifications
|
||||||
} // namespace Platform
|
} // namespace Platform
|
||||||
|
|
|
@ -703,8 +703,8 @@ void MainWindow::showTrayTooltip() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::psUpdateWorkmode() {
|
void MainWindow::workmodeUpdated(DBIWorkMode mode) {
|
||||||
switch (cWorkMode()) {
|
switch (mode) {
|
||||||
case dbiwmWindowAndTray: {
|
case dbiwmWindowAndTray: {
|
||||||
psSetupTrayIcon();
|
psSetupTrayIcon();
|
||||||
HWND psOwner = (HWND)GetWindowLong(ps_hWnd, GWL_HWNDPARENT);
|
HWND psOwner = (HWND)GetWindowLong(ps_hWnd, GWL_HWNDPARENT);
|
||||||
|
@ -800,10 +800,6 @@ void MainWindow::initHook() {
|
||||||
setWindowIcon(wndIcon);
|
setWindowIcon(wndIcon);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MainWindow::psHasNativeNotifications() {
|
|
||||||
return Notifications::Supported();
|
|
||||||
}
|
|
||||||
|
|
||||||
Q_DECLARE_METATYPE(QMargins);
|
Q_DECLARE_METATYPE(QMargins);
|
||||||
void MainWindow::psFirstShow() {
|
void MainWindow::psFirstShow() {
|
||||||
_psShadowWindows.init(st::windowShadowFg->c);
|
_psShadowWindows.init(st::windowShadowFg->c);
|
||||||
|
@ -821,7 +817,7 @@ void MainWindow::psFirstShow() {
|
||||||
|
|
||||||
if ((cLaunchMode() == LaunchModeAutoStart && cStartMinimized() && !App::passcoded()) || cStartInTray()) {
|
if ((cLaunchMode() == LaunchModeAutoStart && cStartMinimized() && !App::passcoded()) || cStartInTray()) {
|
||||||
setWindowState(Qt::WindowMinimized);
|
setWindowState(Qt::WindowMinimized);
|
||||||
if (cWorkMode() == dbiwmTrayOnly || cWorkMode() == dbiwmWindowAndTray) {
|
if (Global::WorkMode().value() == dbiwmTrayOnly || Global::WorkMode().value() == dbiwmWindowAndTray) {
|
||||||
hide();
|
hide();
|
||||||
} else {
|
} else {
|
||||||
show();
|
show();
|
||||||
|
@ -934,18 +930,6 @@ void MainWindow::psUpdateMargins() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::psFlash() {
|
|
||||||
if (GetForegroundWindow() == ps_hWnd) return;
|
|
||||||
|
|
||||||
FLASHWINFO info;
|
|
||||||
info.cbSize = sizeof(info);
|
|
||||||
info.hwnd = ps_hWnd;
|
|
||||||
info.dwFlags = FLASHW_ALL;
|
|
||||||
info.dwTimeout = 0;
|
|
||||||
info.uCount = 1;
|
|
||||||
FlashWindowEx(&info);
|
|
||||||
}
|
|
||||||
|
|
||||||
HWND MainWindow::psHwnd() const {
|
HWND MainWindow::psHwnd() const {
|
||||||
return ps_hWnd;
|
return ps_hWnd;
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,15 +43,8 @@ public:
|
||||||
void psUpdateSysMenu(Qt::WindowState state);
|
void psUpdateSysMenu(Qt::WindowState state);
|
||||||
void psUpdateMargins();
|
void psUpdateMargins();
|
||||||
|
|
||||||
void psFlash();
|
|
||||||
void psNotifySettingGot();
|
|
||||||
|
|
||||||
void psUpdateWorkmode();
|
|
||||||
|
|
||||||
void psRefreshTaskbarIcon();
|
void psRefreshTaskbarIcon();
|
||||||
|
|
||||||
bool psHasNativeNotifications();
|
|
||||||
|
|
||||||
virtual QImage iconWithCounter(int size, int count, style::color bg, style::color fg, bool smallIcon) = 0;
|
virtual QImage iconWithCounter(int size, int count, style::color bg, style::color fg, bool smallIcon) = 0;
|
||||||
|
|
||||||
static UINT TaskbarCreatedMsgId() {
|
static UINT TaskbarCreatedMsgId() {
|
||||||
|
@ -108,6 +101,8 @@ protected:
|
||||||
|
|
||||||
void showTrayTooltip() override;
|
void showTrayTooltip() override;
|
||||||
|
|
||||||
|
void workmodeUpdated(DBIWorkMode mode) override;
|
||||||
|
|
||||||
QTimer psUpdatedPositionTimer;
|
QTimer psUpdatedPositionTimer;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -25,6 +25,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||||
#include "platform/win/windows_event_filter.h"
|
#include "platform/win/windows_event_filter.h"
|
||||||
#include "platform/win/windows_dlls.h"
|
#include "platform/win/windows_dlls.h"
|
||||||
#include "mainwindow.h"
|
#include "mainwindow.h"
|
||||||
|
#include "core/task_queue.h"
|
||||||
|
|
||||||
#include <Shobjidl.h>
|
#include <Shobjidl.h>
|
||||||
#include <shellapi.h>
|
#include <shellapi.h>
|
||||||
|
@ -48,22 +49,6 @@ namespace Platform {
|
||||||
namespace Notifications {
|
namespace Notifications {
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
NeverFreedPointer<Manager> ManagerInstance;
|
|
||||||
|
|
||||||
ComPtr<IToastNotificationManagerStatics> _notificationManager;
|
|
||||||
ComPtr<IToastNotifier> _notifier;
|
|
||||||
ComPtr<IToastNotificationFactory> _notificationFactory;
|
|
||||||
|
|
||||||
struct NotificationPtr {
|
|
||||||
NotificationPtr() {
|
|
||||||
}
|
|
||||||
NotificationPtr(const ComPtr<IToastNotification> &ptr) : p(ptr) {
|
|
||||||
}
|
|
||||||
ComPtr<IToastNotification> p;
|
|
||||||
};
|
|
||||||
using Notifications = QMap<PeerId, QMap<MsgId, NotificationPtr>>;
|
|
||||||
Notifications _notifications;
|
|
||||||
|
|
||||||
class StringReferenceWrapper {
|
class StringReferenceWrapper {
|
||||||
public:
|
public:
|
||||||
StringReferenceWrapper(_In_reads_(length) PCWSTR stringRef, _In_ UINT32 length) throw() {
|
StringReferenceWrapper(_In_reads_(length) PCWSTR stringRef, _In_ UINT32 length) throw() {
|
||||||
|
@ -137,15 +122,6 @@ bool init() {
|
||||||
if (!SUCCEEDED(Dlls::SetCurrentProcessExplicitAppUserModelID(appUserModelId))) {
|
if (!SUCCEEDED(Dlls::SetCurrentProcessExplicitAppUserModelID(appUserModelId))) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (!SUCCEEDED(wrap_GetActivationFactory(StringReferenceWrapper(RuntimeClass_Windows_UI_Notifications_ToastNotificationManager).Get(), &_notificationManager))) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (!SUCCEEDED(_notificationManager->CreateToastNotifierWithId(StringReferenceWrapper(appUserModelId, wcslen(appUserModelId)).Get(), &_notifier))) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (!SUCCEEDED(wrap_GetActivationFactory(StringReferenceWrapper(RuntimeClass_Windows_UI_Notifications_ToastNotification).Get(), &_notificationFactory))) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -235,16 +211,27 @@ typedef ABI::Windows::Foundation::ITypedEventHandler<ToastNotification*, ToastFa
|
||||||
|
|
||||||
class ToastEventHandler : public Implements<DesktopToastActivatedEventHandler, DesktopToastDismissedEventHandler, DesktopToastFailedEventHandler> {
|
class ToastEventHandler : public Implements<DesktopToastActivatedEventHandler, DesktopToastDismissedEventHandler, DesktopToastFailedEventHandler> {
|
||||||
public:
|
public:
|
||||||
ToastEventHandler::ToastEventHandler(const PeerId &peer, MsgId msg) : _ref(1), _peerId(peer), _msgId(msg) {
|
// We keep a weak pointer to a member field of native notifications manager.
|
||||||
|
ToastEventHandler::ToastEventHandler(const std::shared_ptr<Manager*> &guarded, const PeerId &peer, MsgId msg)
|
||||||
|
: _peerId(peer)
|
||||||
|
, _msgId(msg)
|
||||||
|
, _weak(guarded) {
|
||||||
}
|
}
|
||||||
~ToastEventHandler() {
|
~ToastEventHandler() = default;
|
||||||
|
|
||||||
|
void performOnMainQueue(base::lambda_once<void(Manager *manager)> task) {
|
||||||
|
base::TaskQueue::Main().Put([weak = _weak, task = std::move(task)]() mutable {
|
||||||
|
if (auto strong = weak.lock()) {
|
||||||
|
task(*strong);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// DesktopToastActivatedEventHandler
|
// DesktopToastActivatedEventHandler
|
||||||
IFACEMETHODIMP Invoke(_In_ IToastNotification *sender, _In_ IInspectable* args) {
|
IFACEMETHODIMP Invoke(_In_ IToastNotification *sender, _In_ IInspectable* args) {
|
||||||
if (auto manager = ManagerInstance.data()) {
|
performOnMainQueue([peerId = _peerId, msgId = _msgId](Manager *manager) {
|
||||||
manager->notificationActivated(_peerId, _msgId);
|
manager->notificationActivated(peerId, msgId);
|
||||||
}
|
});
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -258,9 +245,9 @@ public:
|
||||||
case ToastDismissalReason_UserCanceled:
|
case ToastDismissalReason_UserCanceled:
|
||||||
case ToastDismissalReason_TimedOut:
|
case ToastDismissalReason_TimedOut:
|
||||||
default:
|
default:
|
||||||
if (auto manager = ManagerInstance.data()) {
|
performOnMainQueue([peerId = _peerId, msgId = _msgId](Manager *manager) {
|
||||||
manager->clearNotification(_peerId, _msgId);
|
manager->clearNotification(peerId, msgId);
|
||||||
}
|
});
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -269,21 +256,23 @@ public:
|
||||||
|
|
||||||
// DesktopToastFailedEventHandler
|
// DesktopToastFailedEventHandler
|
||||||
IFACEMETHODIMP Invoke(_In_ IToastNotification *sender, _In_ IToastFailedEventArgs *e) {
|
IFACEMETHODIMP Invoke(_In_ IToastNotification *sender, _In_ IToastFailedEventArgs *e) {
|
||||||
if (auto manager = ManagerInstance.data()) {
|
performOnMainQueue([peerId = _peerId, msgId = _msgId](Manager *manager) {
|
||||||
manager->clearNotification(_peerId, _msgId);
|
manager->clearNotification(peerId, msgId);
|
||||||
}
|
});
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
// IUnknown
|
// IUnknown
|
||||||
IFACEMETHODIMP_(ULONG) AddRef() {
|
IFACEMETHODIMP_(ULONG) AddRef() {
|
||||||
return InterlockedIncrement(&_ref);
|
return InterlockedIncrement(&_refCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
IFACEMETHODIMP_(ULONG) Release() {
|
IFACEMETHODIMP_(ULONG) Release() {
|
||||||
ULONG l = InterlockedDecrement(&_ref);
|
auto refCount = InterlockedDecrement(&_refCount);
|
||||||
if (l == 0) delete this;
|
if (refCount == 0) {
|
||||||
return l;
|
delete this;
|
||||||
|
}
|
||||||
|
return refCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
IFACEMETHODIMP QueryInterface(_In_ REFIID riid, _COM_Outptr_ void **ppv) {
|
IFACEMETHODIMP QueryInterface(_In_ REFIID riid, _COM_Outptr_ void **ppv) {
|
||||||
|
@ -306,41 +295,61 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ULONG _ref;
|
ULONG _refCount = 0;
|
||||||
PeerId _peerId;
|
PeerId _peerId = 0;
|
||||||
MsgId _msgId;
|
MsgId _msgId = 0;
|
||||||
|
std::weak_ptr<Manager*> _weak;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace
|
auto Checked = false;
|
||||||
|
auto InitSucceeded = false;
|
||||||
|
|
||||||
void Start() {
|
void Check() {
|
||||||
if (init()) {
|
InitSucceeded = init();
|
||||||
ManagerInstance.createIfNull();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Window::Notifications::Manager *GetManager() {
|
} // namespace
|
||||||
if (Global::started() && Global::NativeNotifications()) {
|
|
||||||
return ManagerInstance.data();
|
bool Supported() {
|
||||||
|
if (!Checked) {
|
||||||
|
Checked = true;
|
||||||
|
Check();
|
||||||
|
}
|
||||||
|
return InitSucceeded;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<Window::Notifications::Manager> Create(Window::Notifications::System *system) {
|
||||||
|
if (Global::NativeNotifications() && Supported()) {
|
||||||
|
auto result = std::make_unique<Manager>(system);
|
||||||
|
if (result->init()) {
|
||||||
|
return std::move(result);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Supported() {
|
void FlashBounce() {
|
||||||
return ManagerInstance.data() != nullptr;
|
auto window = App::wnd();
|
||||||
|
if (!window || GetForegroundWindow() == window->psHwnd()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
FLASHWINFO info;
|
||||||
|
info.cbSize = sizeof(info);
|
||||||
|
info.hwnd = window->psHwnd();
|
||||||
|
info.dwFlags = FLASHW_ALL;
|
||||||
|
info.dwTimeout = 0;
|
||||||
|
info.uCount = 1;
|
||||||
|
FlashWindowEx(&info);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Finish() {
|
class Manager::Private {
|
||||||
ManagerInstance.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
class Manager::Impl {
|
|
||||||
public:
|
public:
|
||||||
using Type = Window::Notifications::CachedUserpics::Type;
|
using Type = Window::Notifications::CachedUserpics::Type;
|
||||||
|
|
||||||
Impl(Type type) : _cachedUserpics(type) {
|
explicit Private(Manager *instance, Type type);
|
||||||
}
|
bool init();
|
||||||
|
|
||||||
bool showNotification(PeerData *peer, MsgId msgId, const QString &title, const QString &subtitle, const QString &msg, bool hideNameAndPhoto, bool hideReplyButton);
|
bool showNotification(PeerData *peer, MsgId msgId, const QString &title, const QString &subtitle, const QString &msg, bool hideNameAndPhoto, bool hideReplyButton);
|
||||||
void clearAll();
|
void clearAll();
|
||||||
|
@ -349,21 +358,60 @@ public:
|
||||||
void afterNotificationActivated(PeerId peerId, MsgId msgId);
|
void afterNotificationActivated(PeerId peerId, MsgId msgId);
|
||||||
void clearNotification(PeerId peerId, MsgId msgId);
|
void clearNotification(PeerId peerId, MsgId msgId);
|
||||||
|
|
||||||
~Impl();
|
~Private();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Window::Notifications::CachedUserpics _cachedUserpics;
|
Window::Notifications::CachedUserpics _cachedUserpics;
|
||||||
|
|
||||||
|
std::shared_ptr<Manager*> _guarded;
|
||||||
|
|
||||||
|
ComPtr<IToastNotificationManagerStatics> _notificationManager;
|
||||||
|
ComPtr<IToastNotifier> _notifier;
|
||||||
|
ComPtr<IToastNotificationFactory> _notificationFactory;
|
||||||
|
|
||||||
|
struct NotificationPtr {
|
||||||
|
NotificationPtr() {
|
||||||
|
}
|
||||||
|
NotificationPtr(const ComPtr<IToastNotification> &ptr) : p(ptr) {
|
||||||
|
}
|
||||||
|
|
||||||
|
ComPtr<IToastNotification> p;
|
||||||
|
};
|
||||||
|
QMap<PeerId, QMap<MsgId, NotificationPtr>> _notifications;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
Manager::Impl::~Impl() {
|
Manager::Private::Private(Manager *instance, Type type)
|
||||||
|
: _guarded(std::make_shared<Manager*>(instance))
|
||||||
|
, _cachedUserpics(type) {
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Manager::Private::init() {
|
||||||
|
if (!SUCCEEDED(wrap_GetActivationFactory(StringReferenceWrapper(RuntimeClass_Windows_UI_Notifications_ToastNotificationManager).Get(), &_notificationManager))) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto appUserModelId = AppUserModelId::getId();
|
||||||
|
if (!SUCCEEDED(_notificationManager->CreateToastNotifierWithId(StringReferenceWrapper(appUserModelId, wcslen(appUserModelId)).Get(), &_notifier))) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!SUCCEEDED(wrap_GetActivationFactory(StringReferenceWrapper(RuntimeClass_Windows_UI_Notifications_ToastNotification).Get(), &_notificationFactory))) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
Manager::Private::~Private() {
|
||||||
|
clearAll();
|
||||||
|
|
||||||
_notifications.clear();
|
_notifications.clear();
|
||||||
if (_notificationManager) _notificationManager.Reset();
|
if (_notificationManager) _notificationManager.Reset();
|
||||||
if (_notifier) _notifier.Reset();
|
if (_notifier) _notifier.Reset();
|
||||||
if (_notificationFactory) _notificationFactory.Reset();
|
if (_notificationFactory) _notificationFactory.Reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Manager::Impl::clearAll() {
|
void Manager::Private::clearAll() {
|
||||||
if (!_notifier) return;
|
if (!_notifier) return;
|
||||||
|
|
||||||
auto temp = base::take(_notifications);
|
auto temp = base::take(_notifications);
|
||||||
|
@ -374,7 +422,7 @@ void Manager::Impl::clearAll() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Manager::Impl::clearFromHistory(History *history) {
|
void Manager::Private::clearFromHistory(History *history) {
|
||||||
if (!_notifier) return;
|
if (!_notifier) return;
|
||||||
|
|
||||||
auto i = _notifications.find(history->peer->id);
|
auto i = _notifications.find(history->peer->id);
|
||||||
|
@ -388,17 +436,17 @@ void Manager::Impl::clearFromHistory(History *history) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Manager::Impl::beforeNotificationActivated(PeerId peerId, MsgId msgId) {
|
void Manager::Private::beforeNotificationActivated(PeerId peerId, MsgId msgId) {
|
||||||
clearNotification(peerId, msgId);
|
clearNotification(peerId, msgId);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Manager::Impl::afterNotificationActivated(PeerId peerId, MsgId msgId) {
|
void Manager::Private::afterNotificationActivated(PeerId peerId, MsgId msgId) {
|
||||||
if (auto window = App::wnd()) {
|
if (auto window = App::wnd()) {
|
||||||
SetForegroundWindow(window->psHwnd());
|
SetForegroundWindow(window->psHwnd());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Manager::Impl::clearNotification(PeerId peerId, MsgId msgId) {
|
void Manager::Private::clearNotification(PeerId peerId, MsgId msgId) {
|
||||||
auto i = _notifications.find(peerId);
|
auto i = _notifications.find(peerId);
|
||||||
if (i != _notifications.cend()) {
|
if (i != _notifications.cend()) {
|
||||||
i.value().remove(msgId);
|
i.value().remove(msgId);
|
||||||
|
@ -408,7 +456,7 @@ void Manager::Impl::clearNotification(PeerId peerId, MsgId msgId) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Manager::Impl::showNotification(PeerData *peer, MsgId msgId, const QString &title, const QString &subtitle, const QString &msg, bool hideNameAndPhoto, bool hideReplyButton) {
|
bool Manager::Private::showNotification(PeerData *peer, MsgId msgId, const QString &title, const QString &subtitle, const QString &msg, bool hideNameAndPhoto, bool hideReplyButton) {
|
||||||
if (!_notificationManager || !_notifier || !_notificationFactory) return false;
|
if (!_notificationManager || !_notifier || !_notificationFactory) return false;
|
||||||
|
|
||||||
ComPtr<IXmlDocument> toastXml;
|
ComPtr<IXmlDocument> toastXml;
|
||||||
|
@ -475,7 +523,7 @@ bool Manager::Impl::showNotification(PeerData *peer, MsgId msgId, const QString
|
||||||
if (!SUCCEEDED(hr)) return false;
|
if (!SUCCEEDED(hr)) return false;
|
||||||
|
|
||||||
EventRegistrationToken activatedToken, dismissedToken, failedToken;
|
EventRegistrationToken activatedToken, dismissedToken, failedToken;
|
||||||
ComPtr<ToastEventHandler> eventHandler(new ToastEventHandler(peer->id, msgId));
|
ComPtr<ToastEventHandler> eventHandler(new ToastEventHandler(_guarded, peer->id, msgId));
|
||||||
|
|
||||||
hr = toast->add_Activated(eventHandler.Get(), &activatedToken);
|
hr = toast->add_Activated(eventHandler.Get(), &activatedToken);
|
||||||
if (!SUCCEEDED(hr)) return false;
|
if (!SUCCEEDED(hr)) return false;
|
||||||
|
@ -510,33 +558,38 @@ bool Manager::Impl::showNotification(PeerData *peer, MsgId msgId, const QString
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
Manager::Manager() : _impl(std::make_unique<Impl>(Impl::Type::Rounded)) {
|
Manager::Manager(Window::Notifications::System *system) : NativeManager(system)
|
||||||
|
, _private(std::make_unique<Private>(this, Private::Type::Rounded)) {
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Manager::init() {
|
||||||
|
return _private->init();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Manager::clearNotification(PeerId peerId, MsgId msgId) {
|
void Manager::clearNotification(PeerId peerId, MsgId msgId) {
|
||||||
_impl->clearNotification(peerId, msgId);
|
_private->clearNotification(peerId, msgId);
|
||||||
}
|
}
|
||||||
|
|
||||||
Manager::~Manager() = default;
|
Manager::~Manager() = default;
|
||||||
|
|
||||||
void Manager::doShowNativeNotification(PeerData *peer, MsgId msgId, const QString &title, const QString &subtitle, const QString &msg, bool hideNameAndPhoto, bool hideReplyButton) {
|
void Manager::doShowNativeNotification(PeerData *peer, MsgId msgId, const QString &title, const QString &subtitle, const QString &msg, bool hideNameAndPhoto, bool hideReplyButton) {
|
||||||
_impl->showNotification(peer, msgId, title, subtitle, msg, hideNameAndPhoto, hideReplyButton);
|
_private->showNotification(peer, msgId, title, subtitle, msg, hideNameAndPhoto, hideReplyButton);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Manager::doClearAllFast() {
|
void Manager::doClearAllFast() {
|
||||||
_impl->clearAll();
|
_private->clearAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Manager::doClearFromHistory(History *history) {
|
void Manager::doClearFromHistory(History *history) {
|
||||||
_impl->clearFromHistory(history);
|
_private->clearFromHistory(history);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Manager::onBeforeNotificationActivated(PeerId peerId, MsgId msgId) {
|
void Manager::onBeforeNotificationActivated(PeerId peerId, MsgId msgId) {
|
||||||
_impl->beforeNotificationActivated(peerId, msgId);
|
_private->beforeNotificationActivated(peerId, msgId);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Manager::onAfterNotificationActivated(PeerId peerId, MsgId msgId) {
|
void Manager::onAfterNotificationActivated(PeerId peerId, MsgId msgId) {
|
||||||
_impl->afterNotificationActivated(peerId, msgId);
|
_private->afterNotificationActivated(peerId, msgId);
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
|
@ -30,7 +30,9 @@ inline void CustomNotificationShownHook(QWidget *widget) {
|
||||||
|
|
||||||
class Manager : public Window::Notifications::NativeManager {
|
class Manager : public Window::Notifications::NativeManager {
|
||||||
public:
|
public:
|
||||||
Manager();
|
Manager(Window::Notifications::System *system);
|
||||||
|
|
||||||
|
bool init();
|
||||||
|
|
||||||
void clearNotification(PeerId peerId, MsgId msgId);
|
void clearNotification(PeerId peerId, MsgId msgId);
|
||||||
|
|
||||||
|
@ -44,8 +46,8 @@ protected:
|
||||||
void onAfterNotificationActivated(PeerId peerId, MsgId msgId) override;
|
void onAfterNotificationActivated(PeerId peerId, MsgId msgId) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
class Impl;
|
class Private;
|
||||||
std::unique_ptr<Impl> _impl;
|
const std::unique_ptr<Private> _private;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -24,6 +24,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||||
#include "ui/widgets/popup_menu.h"
|
#include "ui/widgets/popup_menu.h"
|
||||||
#include "styles/style_profile.h"
|
#include "styles/style_profile.h"
|
||||||
#include "styles/style_widgets.h"
|
#include "styles/style_widgets.h"
|
||||||
|
#include "auth_session.h"
|
||||||
|
|
||||||
namespace Profile {
|
namespace Profile {
|
||||||
|
|
||||||
|
@ -38,7 +39,7 @@ PeerListWidget::PeerListWidget(QWidget *parent, PeerData *peer, const QString &t
|
||||||
, _removeText(removeText)
|
, _removeText(removeText)
|
||||||
, _removeWidth(st::normalFont->width(_removeText)) {
|
, _removeWidth(st::normalFont->width(_removeText)) {
|
||||||
setMouseTracking(true);
|
setMouseTracking(true);
|
||||||
subscribe(FileDownload::ImageLoaded(), [this] { update(); });
|
subscribe(AuthSession::CurrentDownloaderTaskFinished(), [this] { update(); });
|
||||||
}
|
}
|
||||||
|
|
||||||
int PeerListWidget::resizeGetHeight(int newWidth) {
|
int PeerListWidget::resizeGetHeight(int newWidth) {
|
||||||
|
|
|
@ -22,7 +22,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||||
|
|
||||||
#include "styles/style_profile.h"
|
#include "styles/style_profile.h"
|
||||||
#include "observer_peer.h"
|
#include "observer_peer.h"
|
||||||
#include "storage/file_download.h"
|
#include "auth_session.h"
|
||||||
|
|
||||||
namespace Profile {
|
namespace Profile {
|
||||||
|
|
||||||
|
@ -41,7 +41,7 @@ UserpicButton::UserpicButton(QWidget *parent, PeerData *peer, int size) : Abstra
|
||||||
subscribe(Notify::PeerUpdated(), Notify::PeerUpdatedHandler(observeEvents, [this](const Notify::PeerUpdate &update) {
|
subscribe(Notify::PeerUpdated(), Notify::PeerUpdatedHandler(observeEvents, [this](const Notify::PeerUpdate &update) {
|
||||||
notifyPeerUpdated(update);
|
notifyPeerUpdated(update);
|
||||||
}));
|
}));
|
||||||
subscribe(FileDownload::ImageLoaded(), [this] {
|
subscribe(AuthSession::CurrentDownloaderTaskFinished(), [this] {
|
||||||
if (_waiting && _peer->userpicLoaded()) {
|
if (_waiting && _peer->userpicLoaded()) {
|
||||||
_waiting = false;
|
_waiting = false;
|
||||||
startNewPhotoShowing();
|
startNewPhotoShowing();
|
||||||
|
|
|
@ -55,7 +55,6 @@ bool gAutoUpdate = true;
|
||||||
TWindowPos gWindowPos;
|
TWindowPos gWindowPos;
|
||||||
LaunchMode gLaunchMode = LaunchModeNormal;
|
LaunchMode gLaunchMode = LaunchModeNormal;
|
||||||
bool gSupportTray = true;
|
bool gSupportTray = true;
|
||||||
DBIWorkMode gWorkMode = dbiwmWindowAndTray;
|
|
||||||
bool gSeenTrayTooltip = false;
|
bool gSeenTrayTooltip = false;
|
||||||
bool gRestartingUpdate = false, gRestarting = false, gRestartingToSettings = false, gWriteProtected = false;
|
bool gRestartingUpdate = false, gRestarting = false, gRestartingToSettings = false, gWriteProtected = false;
|
||||||
int32 gLastUpdateCheck = 0;
|
int32 gLastUpdateCheck = 0;
|
||||||
|
|
|
@ -101,7 +101,6 @@ struct TWindowPos {
|
||||||
};
|
};
|
||||||
DeclareSetting(TWindowPos, WindowPos);
|
DeclareSetting(TWindowPos, WindowPos);
|
||||||
DeclareSetting(bool, SupportTray);
|
DeclareSetting(bool, SupportTray);
|
||||||
DeclareSetting(DBIWorkMode, WorkMode);
|
|
||||||
DeclareSetting(bool, SeenTrayTooltip);
|
DeclareSetting(bool, SeenTrayTooltip);
|
||||||
DeclareSetting(bool, RestartingUpdate);
|
DeclareSetting(bool, RestartingUpdate);
|
||||||
DeclareSetting(bool, Restarting);
|
DeclareSetting(bool, Restarting);
|
||||||
|
|
|
@ -184,9 +184,10 @@ void GeneralWidget::refreshControls() {
|
||||||
#endif // !TDESKTOP_DISABLE_AUTOUPDATE
|
#endif // !TDESKTOP_DISABLE_AUTOUPDATE
|
||||||
|
|
||||||
if (cPlatform() == dbipWindows || cSupportTray()) {
|
if (cPlatform() == dbipWindows || cSupportTray()) {
|
||||||
addChildRow(_enableTrayIcon, marginSmall, lang(lng_settings_workmode_tray), SLOT(onEnableTrayIcon()), (cWorkMode() == dbiwmTrayOnly || cWorkMode() == dbiwmWindowAndTray));
|
auto workMode = Global::WorkMode().value();
|
||||||
|
addChildRow(_enableTrayIcon, marginSmall, lang(lng_settings_workmode_tray), SLOT(onEnableTrayIcon()), (workMode == dbiwmTrayOnly || workMode == dbiwmWindowAndTray));
|
||||||
if (cPlatform() == dbipWindows) {
|
if (cPlatform() == dbipWindows) {
|
||||||
addChildRow(_enableTaskbarIcon, marginLarge, lang(lng_settings_workmode_window), SLOT(onEnableTaskbarIcon()), (cWorkMode() == dbiwmWindowOnly || cWorkMode() == dbiwmWindowAndTray));
|
addChildRow(_enableTaskbarIcon, marginLarge, lang(lng_settings_workmode_window), SLOT(onEnableTaskbarIcon()), (workMode == dbiwmWindowOnly || workMode == dbiwmWindowAndTray));
|
||||||
|
|
||||||
#ifndef OS_WIN_STORE
|
#ifndef OS_WIN_STORE
|
||||||
addChildRow(_autoStart, marginSmall, lang(lng_settings_auto_start), SLOT(onAutoStart()), cAutoStart());
|
addChildRow(_autoStart, marginSmall, lang(lng_settings_auto_start), SLOT(onAutoStart()), cAutoStart());
|
||||||
|
@ -276,12 +277,11 @@ void GeneralWidget::onEnableTaskbarIcon() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void GeneralWidget::updateWorkmode() {
|
void GeneralWidget::updateWorkmode() {
|
||||||
DBIWorkMode newMode = (_enableTrayIcon->checked() && (!_enableTaskbarIcon || _enableTaskbarIcon->checked())) ? dbiwmWindowAndTray : (_enableTrayIcon->checked() ? dbiwmTrayOnly : dbiwmWindowOnly);
|
auto newMode = (_enableTrayIcon->checked() && (!_enableTaskbarIcon || _enableTaskbarIcon->checked())) ? dbiwmWindowAndTray : (_enableTrayIcon->checked() ? dbiwmTrayOnly : dbiwmWindowOnly);
|
||||||
if (cWorkMode() != newMode && (newMode == dbiwmWindowAndTray || newMode == dbiwmTrayOnly)) {
|
if (Global::WorkMode().value() != newMode && (newMode == dbiwmWindowAndTray || newMode == dbiwmTrayOnly)) {
|
||||||
cSetSeenTrayTooltip(false);
|
cSetSeenTrayTooltip(false);
|
||||||
}
|
}
|
||||||
cSetWorkMode(newMode);
|
Global::RefWorkMode().set(newMode);
|
||||||
App::wnd()->psUpdateWorkmode();
|
|
||||||
Local::writeSettings();
|
Local::writeSettings();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -30,18 +30,24 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||||
#include "window/notifications_manager.h"
|
#include "window/notifications_manager.h"
|
||||||
#include "boxes/notifications_box.h"
|
#include "boxes/notifications_box.h"
|
||||||
#include "platform/platform_notifications_manager.h"
|
#include "platform/platform_notifications_manager.h"
|
||||||
|
#include "auth_session.h"
|
||||||
|
|
||||||
namespace Settings {
|
namespace Settings {
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
using ChangeType = Window::Notifications::ChangeType;
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
NotificationsWidget::NotificationsWidget(QWidget *parent, UserData *self) : BlockWidget(parent, self, lang(lng_settings_section_notify)) {
|
NotificationsWidget::NotificationsWidget(QWidget *parent, UserData *self) : BlockWidget(parent, self, lang(lng_settings_section_notify)) {
|
||||||
createControls();
|
createControls();
|
||||||
|
|
||||||
subscribe(Global::RefNotifySettingsChanged(), [this](Notify::ChangeType type) {
|
subscribe(AuthSession::Current().notifications()->settingsChanged(), [this](ChangeType type) {
|
||||||
if (type == Notify::ChangeType::DesktopEnabled) {
|
if (type == ChangeType::DesktopEnabled) {
|
||||||
desktopEnabledUpdated();
|
desktopEnabledUpdated();
|
||||||
} else if (type == Notify::ChangeType::ViewParams) {
|
} else if (type == ChangeType::ViewParams) {
|
||||||
viewParamUpdated();
|
viewParamUpdated();
|
||||||
} else if (type == Notify::ChangeType::SoundEnabled) {
|
} else if (type == ChangeType::SoundEnabled) {
|
||||||
_playSound->setChecked(Global::SoundNotify());
|
_playSound->setChecked(Global::SoundNotify());
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -95,7 +101,7 @@ void NotificationsWidget::onDesktopNotifications() {
|
||||||
}
|
}
|
||||||
Global::SetDesktopNotify(_desktopNotifications->checked());
|
Global::SetDesktopNotify(_desktopNotifications->checked());
|
||||||
Local::writeUserSettings();
|
Local::writeUserSettings();
|
||||||
Global::RefNotifySettingsChanged().notify(Notify::ChangeType::DesktopEnabled);
|
AuthSession::Current().notifications()->settingsChanged().notify(ChangeType::DesktopEnabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
void NotificationsWidget::desktopEnabledUpdated() {
|
void NotificationsWidget::desktopEnabledUpdated() {
|
||||||
|
@ -125,7 +131,7 @@ void NotificationsWidget::onShowSenderName() {
|
||||||
}
|
}
|
||||||
Global::SetNotifyView(viewParam);
|
Global::SetNotifyView(viewParam);
|
||||||
Local::writeUserSettings();
|
Local::writeUserSettings();
|
||||||
Global::RefNotifySettingsChanged().notify(Notify::ChangeType::ViewParams);
|
AuthSession::Current().notifications()->settingsChanged().notify(ChangeType::ViewParams);
|
||||||
}
|
}
|
||||||
|
|
||||||
void NotificationsWidget::onShowMessagePreview() {
|
void NotificationsWidget::onShowMessagePreview() {
|
||||||
|
@ -143,7 +149,7 @@ void NotificationsWidget::onShowMessagePreview() {
|
||||||
|
|
||||||
Global::SetNotifyView(viewParam);
|
Global::SetNotifyView(viewParam);
|
||||||
Local::writeUserSettings();
|
Local::writeUserSettings();
|
||||||
Global::RefNotifySettingsChanged().notify(Notify::ChangeType::ViewParams);
|
AuthSession::Current().notifications()->settingsChanged().notify(ChangeType::ViewParams);
|
||||||
}
|
}
|
||||||
|
|
||||||
void NotificationsWidget::viewParamUpdated() {
|
void NotificationsWidget::viewParamUpdated() {
|
||||||
|
@ -159,10 +165,11 @@ void NotificationsWidget::onNativeNotifications() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Window::Notifications::GetManager()->clearAllFast();
|
|
||||||
Global::SetNativeNotifications(_nativeNotifications->checked());
|
Global::SetNativeNotifications(_nativeNotifications->checked());
|
||||||
Local::writeUserSettings();
|
Local::writeUserSettings();
|
||||||
|
|
||||||
|
AuthSession::Current().notifications()->createManager();
|
||||||
|
|
||||||
if (Global::NativeNotifications()) {
|
if (Global::NativeNotifications()) {
|
||||||
_advanced->slideUp();
|
_advanced->slideUp();
|
||||||
} else {
|
} else {
|
||||||
|
@ -181,13 +188,13 @@ void NotificationsWidget::onPlaySound() {
|
||||||
|
|
||||||
Global::SetSoundNotify(_playSound->checked());
|
Global::SetSoundNotify(_playSound->checked());
|
||||||
Local::writeUserSettings();
|
Local::writeUserSettings();
|
||||||
Global::RefNotifySettingsChanged().notify(Notify::ChangeType::SoundEnabled);
|
AuthSession::Current().notifications()->settingsChanged().notify(ChangeType::SoundEnabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
void NotificationsWidget::onIncludeMuted() {
|
void NotificationsWidget::onIncludeMuted() {
|
||||||
Global::SetIncludeMuted(_includeMuted->checked());
|
Global::SetIncludeMuted(_includeMuted->checked());
|
||||||
Local::writeUserSettings();
|
Local::writeUserSettings();
|
||||||
Global::RefNotifySettingsChanged().notify(Notify::ChangeType::IncludeMuted);
|
AuthSession::Current().notifications()->settingsChanged().notify(ChangeType::IncludeMuted);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Settings
|
} // namespace Settings
|
||||||
|
|
|
@ -46,7 +46,7 @@ bool lock_telegram() {
|
||||||
|
|
||||||
bool minimize_telegram() {
|
bool minimize_telegram() {
|
||||||
if (auto w = App::wnd()) {
|
if (auto w = App::wnd()) {
|
||||||
if (cWorkMode() == dbiwmTrayOnly) {
|
if (Global::WorkMode().value() == dbiwmTrayOnly) {
|
||||||
w->minimizeToTray();
|
w->minimizeToTray();
|
||||||
} else {
|
} else {
|
||||||
w->setWindowState(Qt::WindowMinimized);
|
w->setWindowState(Qt::WindowMinimized);
|
||||||
|
|
|
@ -37,6 +37,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||||
#include "mainwindow.h"
|
#include "mainwindow.h"
|
||||||
#include "apiwrap.h"
|
#include "apiwrap.h"
|
||||||
#include "mainwidget.h"
|
#include "mainwidget.h"
|
||||||
|
#include "auth_session.h"
|
||||||
|
|
||||||
namespace internal {
|
namespace internal {
|
||||||
namespace {
|
namespace {
|
||||||
|
@ -719,7 +720,7 @@ StickerPanInner::StickerPanInner(QWidget *parent) : TWidget(parent)
|
||||||
_updateInlineItems.setSingleShot(true);
|
_updateInlineItems.setSingleShot(true);
|
||||||
connect(&_updateInlineItems, SIGNAL(timeout()), this, SLOT(onUpdateInlineItems()));
|
connect(&_updateInlineItems, SIGNAL(timeout()), this, SLOT(onUpdateInlineItems()));
|
||||||
|
|
||||||
subscribe(FileDownload::ImageLoaded(), [this] {
|
subscribe(AuthSession::CurrentDownloaderTaskFinished(), [this] {
|
||||||
update();
|
update();
|
||||||
readVisibleSets();
|
readVisibleSets();
|
||||||
});
|
});
|
||||||
|
|
|
@ -25,10 +25,18 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||||
#include "messenger.h"
|
#include "messenger.h"
|
||||||
#include "storage/localstorage.h"
|
#include "storage/localstorage.h"
|
||||||
#include "platform/platform_file_utilities.h"
|
#include "platform/platform_file_utilities.h"
|
||||||
|
#include "auth_session.h"
|
||||||
|
|
||||||
|
namespace Storage {
|
||||||
|
|
||||||
|
void Downloader::clearPriorities() {
|
||||||
|
++_priority;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Storage
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
int32 GlobalPriority = 1;
|
|
||||||
struct DataRequested {
|
struct DataRequested {
|
||||||
DataRequested() {
|
DataRequested() {
|
||||||
memset(v, 0, sizeof(v));
|
memset(v, 0, sizeof(v));
|
||||||
|
@ -37,16 +45,15 @@ struct DataRequested {
|
||||||
};
|
};
|
||||||
QMap<int32, DataRequested> DataRequestedMap;
|
QMap<int32, DataRequested> DataRequestedMap;
|
||||||
|
|
||||||
// Debug flag to find out how we end up crashing.
|
} // namespace
|
||||||
std::set<FileLoader*> MustNotDestroy;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
struct FileLoaderQueue {
|
struct FileLoaderQueue {
|
||||||
FileLoaderQueue(int32 limit) : queries(0), limit(limit), start(0), end(0) {
|
FileLoaderQueue(int32 limit) : limit(limit) {
|
||||||
}
|
}
|
||||||
int32 queries, limit;
|
int queries = 0;
|
||||||
FileLoader *start, *end;
|
int limit = 0;
|
||||||
|
FileLoader *start = nullptr;
|
||||||
|
FileLoader *end = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
@ -64,7 +71,8 @@ namespace {
|
||||||
}
|
}
|
||||||
|
|
||||||
FileLoader::FileLoader(const QString &toFile, int32 size, LocationType locationType, LoadToCacheSetting toCache, LoadFromCloudSetting fromCloud, bool autoLoading)
|
FileLoader::FileLoader(const QString &toFile, int32 size, LocationType locationType, LoadToCacheSetting toCache, LoadFromCloudSetting fromCloud, bool autoLoading)
|
||||||
: _autoLoading(autoLoading)
|
: _downloader(AuthSession::Current().downloader())
|
||||||
|
, _autoLoading(autoLoading)
|
||||||
, _file(toFile)
|
, _file(toFile)
|
||||||
, _fname(toFile)
|
, _fname(toFile)
|
||||||
, _toCache(toCache)
|
, _toCache(toCache)
|
||||||
|
@ -158,8 +166,6 @@ void FileLoader::pause() {
|
||||||
}
|
}
|
||||||
|
|
||||||
FileLoader::~FileLoader() {
|
FileLoader::~FileLoader() {
|
||||||
t_assert(MustNotDestroy.find(this) == MustNotDestroy.cend());
|
|
||||||
|
|
||||||
if (_localTaskId) {
|
if (_localTaskId) {
|
||||||
Local::cancelTask(_localTaskId);
|
Local::cancelTask(_localTaskId);
|
||||||
}
|
}
|
||||||
|
@ -197,11 +203,9 @@ void FileLoader::localLoaded(const StorageImageSaved &result, const QByteArray &
|
||||||
_fileIsOpen = false;
|
_fileIsOpen = false;
|
||||||
Platform::File::PostprocessDownloaded(QFileInfo(_file).absoluteFilePath());
|
Platform::File::PostprocessDownloaded(QFileInfo(_file).absoluteFilePath());
|
||||||
}
|
}
|
||||||
FileDownload::ImageLoaded().notify();
|
_downloader->taskFinished().notify();
|
||||||
|
|
||||||
MustNotDestroy.insert(this);
|
|
||||||
emit progress(this);
|
emit progress(this);
|
||||||
MustNotDestroy.erase(this);
|
|
||||||
|
|
||||||
loadNext();
|
loadNext();
|
||||||
}
|
}
|
||||||
|
@ -224,45 +228,46 @@ void FileLoader::start(bool loadFirst, bool prior) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto currentPriority = _downloader->currentPriority();
|
||||||
FileLoader *before = 0, *after = 0;
|
FileLoader *before = 0, *after = 0;
|
||||||
if (prior) {
|
if (prior) {
|
||||||
if (_inQueue && _priority == GlobalPriority) {
|
if (_inQueue && _priority == currentPriority) {
|
||||||
if (loadFirst) {
|
if (loadFirst) {
|
||||||
if (!_prev) return startLoading(loadFirst, prior);
|
if (!_prev) return startLoading(loadFirst, prior);
|
||||||
before = _queue->start;
|
before = _queue->start;
|
||||||
} else {
|
} else {
|
||||||
if (!_next || _next->_priority < GlobalPriority) return startLoading(loadFirst, prior);
|
if (!_next || _next->_priority < currentPriority) return startLoading(loadFirst, prior);
|
||||||
after = _next;
|
after = _next;
|
||||||
while (after->_next && after->_next->_priority == GlobalPriority) {
|
while (after->_next && after->_next->_priority == currentPriority) {
|
||||||
after = after->_next;
|
after = after->_next;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
_priority = GlobalPriority;
|
_priority = currentPriority;
|
||||||
if (loadFirst) {
|
if (loadFirst) {
|
||||||
if (_inQueue && !_prev) return startLoading(loadFirst, prior);
|
if (_inQueue && !_prev) return startLoading(loadFirst, prior);
|
||||||
before = _queue->start;
|
before = _queue->start;
|
||||||
} else {
|
} else {
|
||||||
if (_inQueue) {
|
if (_inQueue) {
|
||||||
if (_next && _next->_priority == GlobalPriority) {
|
if (_next && _next->_priority == currentPriority) {
|
||||||
after = _next;
|
after = _next;
|
||||||
} else if (_prev && _prev->_priority < GlobalPriority) {
|
} else if (_prev && _prev->_priority < currentPriority) {
|
||||||
before = _prev;
|
before = _prev;
|
||||||
while (before->_prev && before->_prev->_priority < GlobalPriority) {
|
while (before->_prev && before->_prev->_priority < currentPriority) {
|
||||||
before = before->_prev;
|
before = before->_prev;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return startLoading(loadFirst, prior);
|
return startLoading(loadFirst, prior);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (_queue->start && _queue->start->_priority == GlobalPriority) {
|
if (_queue->start && _queue->start->_priority == currentPriority) {
|
||||||
after = _queue->start;
|
after = _queue->start;
|
||||||
} else {
|
} else {
|
||||||
before = _queue->start;
|
before = _queue->start;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (after) {
|
if (after) {
|
||||||
while (after->_next && after->_next->_priority == GlobalPriority) {
|
while (after->_next && after->_next->_priority == currentPriority) {
|
||||||
after = after->_next;
|
after = after->_next;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -270,9 +275,9 @@ void FileLoader::start(bool loadFirst, bool prior) {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (loadFirst) {
|
if (loadFirst) {
|
||||||
if (_inQueue && (!_prev || _prev->_priority == GlobalPriority)) return startLoading(loadFirst, prior);
|
if (_inQueue && (!_prev || _prev->_priority == currentPriority)) return startLoading(loadFirst, prior);
|
||||||
before = _prev;
|
before = _prev;
|
||||||
while (before->_prev && before->_prev->_priority != GlobalPriority) {
|
while (before->_prev && before->_prev->_priority != currentPriority) {
|
||||||
before = before->_prev;
|
before = before->_prev;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -330,13 +335,11 @@ void FileLoader::cancel(bool fail) {
|
||||||
_fname = QString();
|
_fname = QString();
|
||||||
_file.setFileName(_fname);
|
_file.setFileName(_fname);
|
||||||
|
|
||||||
MustNotDestroy.insert(this);
|
|
||||||
if (fail) {
|
if (fail) {
|
||||||
emit failed(this, started);
|
emit failed(this, started);
|
||||||
} else {
|
} else {
|
||||||
emit progress(this);
|
emit progress(this);
|
||||||
}
|
}
|
||||||
MustNotDestroy.erase(this);
|
|
||||||
|
|
||||||
loadNext();
|
loadNext();
|
||||||
}
|
}
|
||||||
|
@ -553,12 +556,10 @@ void mtpFileLoader::partLoaded(int32 offset, const MTPupload_File &result, mtpRe
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (_finished) {
|
if (_finished) {
|
||||||
FileDownload::ImageLoaded().notify();
|
_downloader->taskFinished().notify();
|
||||||
}
|
}
|
||||||
|
|
||||||
MustNotDestroy.insert(this);
|
|
||||||
emit progress(this);
|
emit progress(this);
|
||||||
MustNotDestroy.erase(this);
|
|
||||||
|
|
||||||
loadNext();
|
loadNext();
|
||||||
}
|
}
|
||||||
|
@ -609,9 +610,7 @@ bool mtpFileLoader::tryLoadLocal() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
MustNotDestroy.insert(this);
|
|
||||||
emit progress(this);
|
emit progress(this);
|
||||||
MustNotDestroy.erase(this);
|
|
||||||
|
|
||||||
if (_localStatus != LocalNotTried) {
|
if (_localStatus != LocalNotTried) {
|
||||||
return _finished;
|
return _finished;
|
||||||
|
@ -690,11 +689,9 @@ void webFileLoader::onFinished(const QByteArray &data) {
|
||||||
if (_localStatus == LocalNotFound || _localStatus == LocalFailed) {
|
if (_localStatus == LocalNotFound || _localStatus == LocalFailed) {
|
||||||
Local::writeWebFile(_url, _data);
|
Local::writeWebFile(_url, _data);
|
||||||
}
|
}
|
||||||
FileDownload::ImageLoaded().notify();
|
_downloader->taskFinished().notify();
|
||||||
|
|
||||||
MustNotDestroy.insert(this);
|
|
||||||
emit progress(this);
|
emit progress(this);
|
||||||
MustNotDestroy.erase(this);
|
|
||||||
|
|
||||||
loadNext();
|
loadNext();
|
||||||
}
|
}
|
||||||
|
@ -1103,22 +1100,3 @@ void WebLoadMainManager::error(webFileLoader *loader) {
|
||||||
loader->onError();
|
loader->onError();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace MTP {
|
|
||||||
void clearLoaderPriorities() {
|
|
||||||
++GlobalPriority;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace FileDownload {
|
|
||||||
namespace {
|
|
||||||
|
|
||||||
base::Observable<void> ImageLoadedObservable;
|
|
||||||
|
|
||||||
} // namespace
|
|
||||||
|
|
||||||
base::Observable<void> &ImageLoaded() {
|
|
||||||
return ImageLoadedObservable;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace FileDownload
|
|
||||||
|
|
|
@ -21,20 +21,29 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "core/observer.h"
|
#include "core/observer.h"
|
||||||
|
#include "storage/localimageloader.h" // for TaskId
|
||||||
|
|
||||||
namespace MTP {
|
namespace Storage {
|
||||||
void clearLoaderPriorities();
|
|
||||||
}
|
|
||||||
|
|
||||||
enum LocationType {
|
class Downloader final {
|
||||||
UnknownFileLocation = 0,
|
public:
|
||||||
// 1, 2, etc are used as "version" value in mediaKey() method.
|
int currentPriority() const {
|
||||||
|
return _priority;
|
||||||
|
}
|
||||||
|
void clearPriorities();
|
||||||
|
|
||||||
|
base::Observable<void> &taskFinished() {
|
||||||
|
return _taskFinishedObservable;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
base::Observable<void> _taskFinishedObservable;
|
||||||
|
int _priority = 1;
|
||||||
|
|
||||||
DocumentFileLocation = 0x4e45abe9, // mtpc_inputDocumentFileLocation
|
|
||||||
AudioFileLocation = 0x74dc404d, // mtpc_inputAudioFileLocation
|
|
||||||
VideoFileLocation = 0x3d0364ec, // mtpc_inputVideoFileLocation
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
} // namespace Storage
|
||||||
|
|
||||||
struct StorageImageSaved {
|
struct StorageImageSaved {
|
||||||
StorageImageSaved() = default;
|
StorageImageSaved() = default;
|
||||||
explicit StorageImageSaved(const QByteArray &data) : data(data) {
|
explicit StorageImageSaved(const QByteArray &data) : data(data) {
|
||||||
|
@ -52,17 +61,6 @@ enum LocalLoadStatus {
|
||||||
LocalFailed,
|
LocalFailed,
|
||||||
};
|
};
|
||||||
|
|
||||||
using TaskId = void*; // no interface, just id
|
|
||||||
|
|
||||||
enum LoadFromCloudSetting {
|
|
||||||
LoadFromCloudOrLocal,
|
|
||||||
LoadFromLocalOnly,
|
|
||||||
};
|
|
||||||
enum LoadToCacheSetting {
|
|
||||||
LoadToFileOnly,
|
|
||||||
LoadToCacheAsWell,
|
|
||||||
};
|
|
||||||
|
|
||||||
class mtpFileLoader;
|
class mtpFileLoader;
|
||||||
class webFileLoader;
|
class webFileLoader;
|
||||||
|
|
||||||
|
@ -129,6 +127,7 @@ signals:
|
||||||
protected:
|
protected:
|
||||||
void readImage(const QSize &shrinkBox) const;
|
void readImage(const QSize &shrinkBox) const;
|
||||||
|
|
||||||
|
Storage::Downloader *_downloader = nullptr;
|
||||||
FileLoader *_prev = nullptr;
|
FileLoader *_prev = nullptr;
|
||||||
FileLoader *_next = nullptr;
|
FileLoader *_next = nullptr;
|
||||||
int _priority = 0;
|
int _priority = 0;
|
||||||
|
@ -338,9 +337,3 @@ static WebLoadManager * const FinishedWebLoadManager = SharedMemoryLocation<WebL
|
||||||
|
|
||||||
void reinitWebLoadManager();
|
void reinitWebLoadManager();
|
||||||
void stopWebLoadManager();
|
void stopWebLoadManager();
|
||||||
|
|
||||||
namespace FileDownload {
|
|
||||||
|
|
||||||
base::Observable<void> &ImageLoaded();
|
|
||||||
|
|
||||||
} // namespace FileDownload
|
|
||||||
|
|
|
@ -99,6 +99,8 @@ struct SendMediaReady {
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
using TaskId = void*; // no interface, just id
|
||||||
|
|
||||||
class Task {
|
class Task {
|
||||||
public:
|
public:
|
||||||
virtual void process() = 0; // is executed in a separate thread
|
virtual void process() = 0; // is executed in a separate thread
|
||||||
|
|
|
@ -1088,11 +1088,14 @@ bool _readSetting(quint32 blockId, QDataStream &stream, int version, ReadSetting
|
||||||
stream >> v;
|
stream >> v;
|
||||||
if (!_checkStreamStatus(stream)) return false;
|
if (!_checkStreamStatus(stream)) return false;
|
||||||
|
|
||||||
switch (v) {
|
auto newMode = [v] {
|
||||||
case dbiwmTrayOnly: cSetWorkMode(dbiwmTrayOnly); break;
|
switch (v) {
|
||||||
case dbiwmWindowOnly: cSetWorkMode(dbiwmWindowOnly); break;
|
case dbiwmTrayOnly: return dbiwmTrayOnly;
|
||||||
default: cSetWorkMode(dbiwmWindowAndTray); break;
|
case dbiwmWindowOnly: return dbiwmWindowOnly;
|
||||||
|
};
|
||||||
|
return dbiwmWindowAndTray;
|
||||||
};
|
};
|
||||||
|
Global::RefWorkMode().set(newMode());
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case dbiConnectionType: {
|
case dbiConnectionType: {
|
||||||
|
@ -2269,7 +2272,7 @@ void writeSettings() {
|
||||||
data.stream << quint32(dbiAutoStart) << qint32(cAutoStart());
|
data.stream << quint32(dbiAutoStart) << qint32(cAutoStart());
|
||||||
data.stream << quint32(dbiStartMinimized) << qint32(cStartMinimized());
|
data.stream << quint32(dbiStartMinimized) << qint32(cStartMinimized());
|
||||||
data.stream << quint32(dbiSendToMenu) << qint32(cSendToMenu());
|
data.stream << quint32(dbiSendToMenu) << qint32(cSendToMenu());
|
||||||
data.stream << quint32(dbiWorkMode) << qint32(cWorkMode());
|
data.stream << quint32(dbiWorkMode) << qint32(Global::WorkMode().value());
|
||||||
data.stream << quint32(dbiSeenTrayTooltip) << qint32(cSeenTrayTooltip());
|
data.stream << quint32(dbiSeenTrayTooltip) << qint32(cSeenTrayTooltip());
|
||||||
data.stream << quint32(dbiAutoUpdate) << qint32(cAutoUpdate());
|
data.stream << quint32(dbiAutoUpdate) << qint32(cAutoUpdate());
|
||||||
data.stream << quint32(dbiLastUpdateCheck) << qint32(cLastUpdateCheck());
|
data.stream << quint32(dbiLastUpdateCheck) << qint32(cLastUpdateCheck());
|
||||||
|
@ -2731,7 +2734,7 @@ public:
|
||||||
qint32 legacyTypeField = 0;
|
qint32 legacyTypeField = 0;
|
||||||
stream >> first >> second >> legacyTypeField >> data;
|
stream >> first >> second >> legacyTypeField >> data;
|
||||||
}
|
}
|
||||||
void clearInMap() {
|
void clearInMap() override {
|
||||||
StorageMap::iterator j = _imagesMap.find(_location);
|
StorageMap::iterator j = _imagesMap.find(_location);
|
||||||
if (j != _imagesMap.cend() && j->first == _key) {
|
if (j != _imagesMap.cend() && j->first == _key) {
|
||||||
clearKey(_key, FileOption::User);
|
clearKey(_key, FileOption::User);
|
||||||
|
|
|
@ -21,6 +21,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "core/basic_types.h"
|
#include "core/basic_types.h"
|
||||||
|
#include "storage/file_download.h"
|
||||||
|
|
||||||
namespace Window {
|
namespace Window {
|
||||||
namespace Theme {
|
namespace Theme {
|
||||||
|
|
|
@ -37,6 +37,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||||
#include "window/themes/window_theme.h"
|
#include "window/themes/window_theme.h"
|
||||||
#include "auth_session.h"
|
#include "auth_session.h"
|
||||||
#include "messenger.h"
|
#include "messenger.h"
|
||||||
|
#include "storage/file_download.h"
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
|
|
|
@ -20,6 +20,34 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||||
*/
|
*/
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
using MediaKey = QPair<uint64, uint64>;
|
||||||
|
|
||||||
|
inline uint64 mediaMix32To64(int32 a, int32 b) {
|
||||||
|
return (uint64(*reinterpret_cast<uint32*>(&a)) << 32) | uint64(*reinterpret_cast<uint32*>(&b));
|
||||||
|
}
|
||||||
|
|
||||||
|
enum LocationType {
|
||||||
|
UnknownFileLocation = 0,
|
||||||
|
// 1, 2, etc are used as "version" value in mediaKey() method.
|
||||||
|
|
||||||
|
DocumentFileLocation = 0x4e45abe9, // mtpc_inputDocumentFileLocation
|
||||||
|
AudioFileLocation = 0x74dc404d, // mtpc_inputAudioFileLocation
|
||||||
|
VideoFileLocation = 0x3d0364ec, // mtpc_inputVideoFileLocation
|
||||||
|
};
|
||||||
|
|
||||||
|
// Old method, should not be used anymore.
|
||||||
|
//inline MediaKey mediaKey(LocationType type, int32 dc, const uint64 &id) {
|
||||||
|
// return MediaKey(mediaMix32To64(type, dc), id);
|
||||||
|
//}
|
||||||
|
// New method when version was introduced, type is not relevant anymore (all files are Documents).
|
||||||
|
inline MediaKey mediaKey(LocationType type, int32 dc, const uint64 &id, int32 version) {
|
||||||
|
return (version > 0) ? MediaKey(mediaMix32To64(version, dc), id) : MediaKey(mediaMix32To64(type, dc), id);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline StorageKey mediaKey(const MTPDfileLocation &location) {
|
||||||
|
return storageKey(location.vdc_id.v, location.vvolume_id.v, location.vlocal_id.v);
|
||||||
|
}
|
||||||
|
|
||||||
typedef int32 UserId;
|
typedef int32 UserId;
|
||||||
typedef int32 ChatId;
|
typedef int32 ChatId;
|
||||||
typedef int32 ChannelId;
|
typedef int32 ChannelId;
|
||||||
|
|
|
@ -883,6 +883,10 @@ void RemoteImage::setData(QByteArray &bytes, const QByteArray &bytesFormat) {
|
||||||
_forgot = false;
|
_forgot = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool RemoteImage::amLoading() const {
|
||||||
|
return _loader && _loader != CancelledFileLoader;
|
||||||
|
}
|
||||||
|
|
||||||
void RemoteImage::automaticLoad(const HistoryItem *item) {
|
void RemoteImage::automaticLoad(const HistoryItem *item) {
|
||||||
if (loaded()) return;
|
if (loaded()) return;
|
||||||
|
|
||||||
|
|
|
@ -20,7 +20,18 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||||
*/
|
*/
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "storage/file_download.h"
|
class FileLoader;
|
||||||
|
class mtpFileLoader;
|
||||||
|
|
||||||
|
enum LoadFromCloudSetting {
|
||||||
|
LoadFromCloudOrLocal,
|
||||||
|
LoadFromLocalOnly,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum LoadToCacheSetting {
|
||||||
|
LoadToFileOnly,
|
||||||
|
LoadToCacheAsWell,
|
||||||
|
};
|
||||||
|
|
||||||
enum class ImageRoundRadius {
|
enum class ImageRoundRadius {
|
||||||
None,
|
None,
|
||||||
|
@ -317,9 +328,7 @@ protected:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
mutable FileLoader *_loader = nullptr;
|
mutable FileLoader *_loader = nullptr;
|
||||||
bool amLoading() const {
|
bool amLoading() const;
|
||||||
return _loader && _loader != CancelledFileLoader;
|
|
||||||
}
|
|
||||||
void doCheckload() const;
|
void doCheckload() const;
|
||||||
|
|
||||||
void destroyLoaderDelayed(FileLoader *newValue = nullptr) const;
|
void destroyLoaderDelayed(FileLoader *newValue = nullptr) const;
|
||||||
|
@ -328,7 +337,6 @@ private:
|
||||||
|
|
||||||
class StorageImage : public RemoteImage {
|
class StorageImage : public RemoteImage {
|
||||||
public:
|
public:
|
||||||
|
|
||||||
StorageImage(const StorageImageLocation &location, int32 size = 0);
|
StorageImage(const StorageImageLocation &location, int32 size = 0);
|
||||||
StorageImage(const StorageImageLocation &location, QByteArray &bytes);
|
StorageImage(const StorageImageLocation &location, QByteArray &bytes);
|
||||||
|
|
||||||
|
@ -511,19 +519,3 @@ inline bool operator==(const FileLocation &a, const FileLocation &b) {
|
||||||
inline bool operator!=(const FileLocation &a, const FileLocation &b) {
|
inline bool operator!=(const FileLocation &a, const FileLocation &b) {
|
||||||
return !(a == b);
|
return !(a == b);
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef QPair<uint64, uint64> MediaKey;
|
|
||||||
inline uint64 mediaMix32To64(int32 a, int32 b) {
|
|
||||||
return (uint64(*reinterpret_cast<uint32*>(&a)) << 32) | uint64(*reinterpret_cast<uint32*>(&b));
|
|
||||||
}
|
|
||||||
// Old method, should not be used anymore.
|
|
||||||
//inline MediaKey mediaKey(LocationType type, int32 dc, const uint64 &id) {
|
|
||||||
// return MediaKey(mediaMix32To64(type, dc), id);
|
|
||||||
//}
|
|
||||||
// New method when version was introduced, type is not relevant anymore (all files are Documents).
|
|
||||||
inline MediaKey mediaKey(LocationType type, int32 dc, const uint64 &id, int32 version) {
|
|
||||||
return (version > 0) ? MediaKey(mediaMix32To64(version, dc), id) : MediaKey(mediaMix32To64(type, dc), id);
|
|
||||||
}
|
|
||||||
inline StorageKey mediaKey(const MTPDfileLocation &location) {
|
|
||||||
return storageKey(location.vdc_id.v, location.vvolume_id.v, location.vlocal_id.v);
|
|
||||||
}
|
|
||||||
|
|
|
@ -43,6 +43,7 @@ MainWindow::MainWindow() : QWidget()
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
subscribe(Global::RefUnreadCounterUpdate(), [this] { updateUnreadCounter(); });
|
subscribe(Global::RefUnreadCounterUpdate(), [this] { updateUnreadCounter(); });
|
||||||
|
subscribe(Global::RefWorkMode(), [this](DBIWorkMode mode) { workmodeUpdated(mode); });
|
||||||
|
|
||||||
_isActiveTimer->setSingleShot(true);
|
_isActiveTimer->setSingleShot(true);
|
||||||
connect(_isActiveTimer, SIGNAL(timeout()), this, SLOT(updateIsActiveByTimer()));
|
connect(_isActiveTimer, SIGNAL(timeout()), this, SLOT(updateIsActiveByTimer()));
|
||||||
|
@ -53,7 +54,7 @@ bool MainWindow::hideNoQuit() {
|
||||||
hideMediaview();
|
hideMediaview();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (cWorkMode() == dbiwmTrayOnly || cWorkMode() == dbiwmWindowAndTray) {
|
if (Global::WorkMode().value() == dbiwmTrayOnly || Global::WorkMode().value() == dbiwmWindowAndTray) {
|
||||||
if (minimizeToTray()) {
|
if (minimizeToTray()) {
|
||||||
Ui::showChatsList();
|
Ui::showChatsList();
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -127,6 +127,9 @@ protected:
|
||||||
virtual void showTrayTooltip() {
|
virtual void showTrayTooltip() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual void workmodeUpdated(DBIWorkMode mode) {
|
||||||
|
}
|
||||||
|
|
||||||
virtual void updateControlsGeometry();
|
virtual void updateControlsGeometry();
|
||||||
|
|
||||||
// This one is overriden in Windows for historical reasons.
|
// This one is overriden in Windows for historical reasons.
|
||||||
|
|
|
@ -25,25 +25,332 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||||
#include "lang.h"
|
#include "lang.h"
|
||||||
#include "mainwindow.h"
|
#include "mainwindow.h"
|
||||||
#include "mainwidget.h"
|
#include "mainwidget.h"
|
||||||
|
#include "apiwrap.h"
|
||||||
|
#include "auth_session.h"
|
||||||
|
|
||||||
namespace Window {
|
namespace Window {
|
||||||
namespace Notifications {
|
namespace Notifications {
|
||||||
|
|
||||||
void Start() {
|
System::System(AuthSession *session) : _authSession(session) {
|
||||||
Default::Start();
|
createManager();
|
||||||
Platform::Notifications::Start();
|
|
||||||
|
_waitTimer.setTimeoutHandler([this] {
|
||||||
|
showNext();
|
||||||
|
});
|
||||||
|
|
||||||
|
subscribe(settingsChanged(), [this](ChangeType type) {
|
||||||
|
if (type == ChangeType::DesktopEnabled) {
|
||||||
|
App::wnd()->updateTrayMenu();
|
||||||
|
clearAll();
|
||||||
|
} else if (type == ChangeType::ViewParams) {
|
||||||
|
updateAll();
|
||||||
|
} else if (type == ChangeType::IncludeMuted) {
|
||||||
|
Notify::unreadCounterUpdated();
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
Manager *GetManager() {
|
void System::createManager() {
|
||||||
if (auto result = Platform::Notifications::GetManager()) {
|
_manager = Platform::Notifications::Create(this);
|
||||||
return result;
|
if (!_manager) {
|
||||||
|
_manager = std::make_unique<Default::Manager>(this);
|
||||||
}
|
}
|
||||||
return Default::GetManager();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Finish() {
|
void System::schedule(History *history, HistoryItem *item) {
|
||||||
Platform::Notifications::Finish();
|
if (App::quitting() || !history->currentNotification() || !App::api()) return;
|
||||||
Default::Finish();
|
|
||||||
|
PeerData *notifyByFrom = (!history->peer->isUser() && item->mentionsMe()) ? item->from() : 0;
|
||||||
|
|
||||||
|
if (item->isSilent()) {
|
||||||
|
history->popNotification(item);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool haveSetting = (history->peer->notify != UnknownNotifySettings);
|
||||||
|
if (haveSetting) {
|
||||||
|
if (history->peer->notify != EmptyNotifySettings && history->peer->notify->mute > unixtime()) {
|
||||||
|
if (notifyByFrom) {
|
||||||
|
haveSetting = (item->from()->notify != UnknownNotifySettings);
|
||||||
|
if (haveSetting) {
|
||||||
|
if (notifyByFrom->notify != EmptyNotifySettings && notifyByFrom->notify->mute > unixtime()) {
|
||||||
|
history->popNotification(item);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
App::api()->requestNotifySetting(notifyByFrom);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
history->popNotification(item);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (notifyByFrom && notifyByFrom->notify == UnknownNotifySettings) {
|
||||||
|
App::api()->requestNotifySetting(notifyByFrom);
|
||||||
|
}
|
||||||
|
App::api()->requestNotifySetting(history->peer);
|
||||||
|
}
|
||||||
|
if (!item->notificationReady()) {
|
||||||
|
haveSetting = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
int delay = item->Has<HistoryMessageForwarded>() ? 500 : 100, t = unixtime();
|
||||||
|
auto ms = getms(true);
|
||||||
|
bool isOnline = App::main()->lastWasOnline(), otherNotOld = ((cOtherOnline() * 1000LL) + Global::OnlineCloudTimeout() > t * 1000LL);
|
||||||
|
bool otherLaterThanMe = (cOtherOnline() * 1000LL + (ms - App::main()->lastSetOnline()) > t * 1000LL);
|
||||||
|
if (!isOnline && otherNotOld && otherLaterThanMe) {
|
||||||
|
delay = Global::NotifyCloudDelay();
|
||||||
|
} else if (cOtherOnline() >= t) {
|
||||||
|
delay = Global::NotifyDefaultDelay();
|
||||||
|
}
|
||||||
|
|
||||||
|
auto when = ms + delay;
|
||||||
|
_whenAlerts[history].insert(when, notifyByFrom);
|
||||||
|
if (Global::DesktopNotify() && !Platform::Notifications::SkipToast()) {
|
||||||
|
auto &whenMap = _whenMaps[history];
|
||||||
|
if (whenMap.constFind(item->id) == whenMap.cend()) {
|
||||||
|
whenMap.insert(item->id, when);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto &addTo = haveSetting ? _waiters : _settingWaiters;
|
||||||
|
auto it = addTo.constFind(history);
|
||||||
|
if (it == addTo.cend() || it->when > when) {
|
||||||
|
addTo.insert(history, Waiter(item->id, when, notifyByFrom));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (haveSetting) {
|
||||||
|
if (!_waitTimer.isActive() || _waitTimer.remainingTime() > delay) {
|
||||||
|
_waitTimer.start(delay);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void System::clearAll() {
|
||||||
|
_manager->clearAll();
|
||||||
|
|
||||||
|
for (auto i = _whenMaps.cbegin(), e = _whenMaps.cend(); i != e; ++i) {
|
||||||
|
i.key()->clearNotifications();
|
||||||
|
}
|
||||||
|
_whenMaps.clear();
|
||||||
|
_whenAlerts.clear();
|
||||||
|
_waiters.clear();
|
||||||
|
_settingWaiters.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void System::clearFromHistory(History *history) {
|
||||||
|
_manager->clearFromHistory(history);
|
||||||
|
|
||||||
|
history->clearNotifications();
|
||||||
|
_whenMaps.remove(history);
|
||||||
|
_whenAlerts.remove(history);
|
||||||
|
_waiters.remove(history);
|
||||||
|
_settingWaiters.remove(history);
|
||||||
|
|
||||||
|
_waitTimer.stop();
|
||||||
|
showNext();
|
||||||
|
}
|
||||||
|
|
||||||
|
void System::clearFromItem(HistoryItem *item) {
|
||||||
|
_manager->clearFromItem(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
void System::clearAllFast() {
|
||||||
|
_manager->clearAllFast();
|
||||||
|
|
||||||
|
_whenMaps.clear();
|
||||||
|
_whenAlerts.clear();
|
||||||
|
_waiters.clear();
|
||||||
|
_settingWaiters.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void System::checkDelayed() {
|
||||||
|
int32 t = unixtime();
|
||||||
|
for (auto i = _settingWaiters.begin(); i != _settingWaiters.end();) {
|
||||||
|
auto history = i.key();
|
||||||
|
bool loaded = false, muted = false;
|
||||||
|
if (history->peer->notify != UnknownNotifySettings) {
|
||||||
|
if (history->peer->notify == EmptyNotifySettings || history->peer->notify->mute <= t) {
|
||||||
|
loaded = true;
|
||||||
|
} else if (PeerData *from = i.value().notifyByFrom) {
|
||||||
|
if (from->notify != UnknownNotifySettings) {
|
||||||
|
if (from->notify == EmptyNotifySettings || from->notify->mute <= t) {
|
||||||
|
loaded = true;
|
||||||
|
} else {
|
||||||
|
loaded = muted = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
loaded = muted = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (loaded) {
|
||||||
|
if (HistoryItem *item = App::histItemById(history->channelId(), i.value().msg)) {
|
||||||
|
if (!item->notificationReady()) {
|
||||||
|
loaded = false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
muted = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (loaded) {
|
||||||
|
if (!muted) {
|
||||||
|
_waiters.insert(i.key(), i.value());
|
||||||
|
}
|
||||||
|
i = _settingWaiters.erase(i);
|
||||||
|
} else {
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_waitTimer.stop();
|
||||||
|
showNext();
|
||||||
|
}
|
||||||
|
|
||||||
|
void System::showNext() {
|
||||||
|
if (App::quitting()) return;
|
||||||
|
|
||||||
|
auto ms = getms(true), nextAlert = 0LL;
|
||||||
|
bool alert = false;
|
||||||
|
int32 now = unixtime();
|
||||||
|
for (auto i = _whenAlerts.begin(); i != _whenAlerts.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
|
||||||
|
i.value().erase(i.value().begin());
|
||||||
|
}
|
||||||
|
if (n == EmptyNotifySettings || (n != UnknownNotifySettings && n->mute <= now)) {
|
||||||
|
alert = true;
|
||||||
|
} else if (f == EmptyNotifySettings || (f != UnknownNotifySettings && f->mute <= now)) { // notify by from()
|
||||||
|
alert = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (i.value().isEmpty()) {
|
||||||
|
i = _whenAlerts.erase(i);
|
||||||
|
} else {
|
||||||
|
if (!nextAlert || nextAlert > i.value().begin().key()) {
|
||||||
|
nextAlert = i.value().begin().key();
|
||||||
|
}
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (alert) {
|
||||||
|
Platform::Notifications::FlashBounce();
|
||||||
|
App::playSound();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_waiters.isEmpty() || !Global::DesktopNotify() || Platform::Notifications::SkipToast()) {
|
||||||
|
if (nextAlert) {
|
||||||
|
_waitTimer.start(nextAlert - ms);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
auto next = 0LL;
|
||||||
|
HistoryItem *notifyItem = nullptr;
|
||||||
|
History *notifyHistory = nullptr;
|
||||||
|
for (auto i = _waiters.begin(); i != _waiters.end();) {
|
||||||
|
History *history = i.key();
|
||||||
|
if (history->currentNotification() && history->currentNotification()->id != i.value().msg) {
|
||||||
|
auto j = _whenMaps.find(history);
|
||||||
|
if (j == _whenMaps.end()) {
|
||||||
|
history->clearNotifications();
|
||||||
|
i = _waiters.erase(i);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
do {
|
||||||
|
auto k = j.value().constFind(history->currentNotification()->id);
|
||||||
|
if (k != j.value().cend()) {
|
||||||
|
i.value().msg = k.key();
|
||||||
|
i.value().when = k.value();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
history->skipNotification();
|
||||||
|
} while (history->currentNotification());
|
||||||
|
}
|
||||||
|
if (!history->currentNotification()) {
|
||||||
|
_whenMaps.remove(history);
|
||||||
|
i = _waiters.erase(i);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
auto when = i.value().when;
|
||||||
|
if (!notifyItem || next > when) {
|
||||||
|
next = when;
|
||||||
|
notifyItem = history->currentNotification();
|
||||||
|
notifyHistory = history;
|
||||||
|
}
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
if (notifyItem) {
|
||||||
|
if (next > ms) {
|
||||||
|
if (nextAlert && nextAlert < next) {
|
||||||
|
next = nextAlert;
|
||||||
|
nextAlert = 0;
|
||||||
|
}
|
||||||
|
_waitTimer.start(next - ms);
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
HistoryItem *fwd = notifyItem->Has<HistoryMessageForwarded>() ? notifyItem : nullptr; // forwarded notify grouping
|
||||||
|
int32 fwdCount = 1;
|
||||||
|
|
||||||
|
auto ms = getms(true);
|
||||||
|
History *history = notifyItem->history();
|
||||||
|
auto j = _whenMaps.find(history);
|
||||||
|
if (j == _whenMaps.cend()) {
|
||||||
|
history->clearNotifications();
|
||||||
|
} else {
|
||||||
|
HistoryItem *nextNotify = 0;
|
||||||
|
do {
|
||||||
|
history->skipNotification();
|
||||||
|
if (!history->hasNotification()) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
j.value().remove((fwd ? fwd : notifyItem)->id);
|
||||||
|
do {
|
||||||
|
auto k = j.value().constFind(history->currentNotification()->id);
|
||||||
|
if (k != j.value().cend()) {
|
||||||
|
nextNotify = history->currentNotification();
|
||||||
|
_waiters.insert(notifyHistory, Waiter(k.key(), k.value(), 0));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
history->skipNotification();
|
||||||
|
} while (history->hasNotification());
|
||||||
|
if (nextNotify) {
|
||||||
|
if (fwd) {
|
||||||
|
HistoryItem *nextFwd = nextNotify->Has<HistoryMessageForwarded>() ? nextNotify : nullptr;
|
||||||
|
if (nextFwd && fwd->author() == nextFwd->author() && qAbs(int64(nextFwd->date.toTime_t()) - int64(fwd->date.toTime_t())) < 2) {
|
||||||
|
fwd = nextFwd;
|
||||||
|
++fwdCount;
|
||||||
|
} else {
|
||||||
|
nextNotify = nullptr;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
nextNotify = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} while (nextNotify);
|
||||||
|
}
|
||||||
|
|
||||||
|
_manager->showNotification(notifyItem, fwdCount);
|
||||||
|
|
||||||
|
if (!history->hasNotification()) {
|
||||||
|
_waiters.remove(history);
|
||||||
|
_whenMaps.remove(history);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (nextAlert) {
|
||||||
|
_waitTimer.start(nextAlert - ms);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void System::updateAll() {
|
||||||
|
_manager->updateAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
Manager::DisplayOptions Manager::getNotificationOptions(HistoryItem *item) {
|
Manager::DisplayOptions Manager::getNotificationOptions(HistoryItem *item) {
|
||||||
|
@ -66,7 +373,7 @@ void Manager::notificationActivated(PeerId peerId, MsgId msgId) {
|
||||||
#endif
|
#endif
|
||||||
if (App::passcoded()) {
|
if (App::passcoded()) {
|
||||||
window->setInnerFocus();
|
window->setInnerFocus();
|
||||||
window->notifyClear();
|
system()->clearAll();
|
||||||
} else {
|
} else {
|
||||||
auto tomsg = !history->peer->isUser() && (msgId > 0);
|
auto tomsg = !history->peer->isUser() && (msgId > 0);
|
||||||
if (tomsg) {
|
if (tomsg) {
|
||||||
|
@ -76,7 +383,7 @@ void Manager::notificationActivated(PeerId peerId, MsgId msgId) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ui::showPeerHistory(history, tomsg ? msgId : ShowAtUnreadMsgId);
|
Ui::showPeerHistory(history, tomsg ? msgId : ShowAtUnreadMsgId);
|
||||||
window->notifyClear(history);
|
system()->clearFromHistory(history);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
onAfterNotificationActivated(peerId, msgId);
|
onAfterNotificationActivated(peerId, msgId);
|
||||||
|
|
|
@ -20,17 +20,100 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||||
*/
|
*/
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
class AuthSession;
|
||||||
|
|
||||||
|
namespace Platform {
|
||||||
|
namespace Notifications {
|
||||||
|
class Manager;
|
||||||
|
} // namespace Notifications
|
||||||
|
} // namespace Platform
|
||||||
|
|
||||||
|
namespace Window {
|
||||||
|
namespace Notifications {
|
||||||
|
|
||||||
|
enum class ChangeType {
|
||||||
|
SoundEnabled,
|
||||||
|
IncludeMuted,
|
||||||
|
DesktopEnabled,
|
||||||
|
ViewParams,
|
||||||
|
MaxCount,
|
||||||
|
Corner,
|
||||||
|
DemoIsShown,
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Notifications
|
||||||
|
} // namespace Window
|
||||||
|
|
||||||
|
namespace base {
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct custom_is_fast_copy_type<Window::Notifications::ChangeType> : public std::true_type {
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace base
|
||||||
|
|
||||||
namespace Window {
|
namespace Window {
|
||||||
namespace Notifications {
|
namespace Notifications {
|
||||||
|
|
||||||
class Manager;
|
class Manager;
|
||||||
|
|
||||||
void Start();
|
class System final : private base::Subscriber {
|
||||||
Manager *GetManager();
|
public:
|
||||||
void Finish();
|
System(AuthSession *session);
|
||||||
|
|
||||||
|
void createManager();
|
||||||
|
|
||||||
|
void checkDelayed();
|
||||||
|
void schedule(History *history, HistoryItem *item);
|
||||||
|
void clearFromHistory(History *history);
|
||||||
|
void clearFromItem(HistoryItem *item);
|
||||||
|
void clearAll();
|
||||||
|
void clearAllFast();
|
||||||
|
void updateAll();
|
||||||
|
|
||||||
|
base::Observable<ChangeType> &settingsChanged() {
|
||||||
|
return _settingsChanged;
|
||||||
|
}
|
||||||
|
|
||||||
|
AuthSession *authSession() {
|
||||||
|
return _authSession;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
void showNext();
|
||||||
|
|
||||||
|
AuthSession *_authSession = nullptr;
|
||||||
|
|
||||||
|
QMap<History*, QMap<MsgId, TimeMs>> _whenMaps;
|
||||||
|
|
||||||
|
struct Waiter {
|
||||||
|
Waiter(MsgId msg, TimeMs when, PeerData *notifyByFrom)
|
||||||
|
: msg(msg)
|
||||||
|
, when(when)
|
||||||
|
, notifyByFrom(notifyByFrom) {
|
||||||
|
}
|
||||||
|
MsgId msg;
|
||||||
|
TimeMs when;
|
||||||
|
PeerData *notifyByFrom;
|
||||||
|
};
|
||||||
|
using Waiters = QMap<History*, Waiter>;
|
||||||
|
Waiters _waiters;
|
||||||
|
Waiters _settingWaiters;
|
||||||
|
SingleTimer _waitTimer;
|
||||||
|
|
||||||
|
QMap<History*, QMap<TimeMs, PeerData*>> _whenAlerts;
|
||||||
|
|
||||||
|
std::unique_ptr<Manager> _manager;
|
||||||
|
|
||||||
|
base::Observable<ChangeType> _settingsChanged;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
class Manager {
|
class Manager {
|
||||||
public:
|
public:
|
||||||
|
Manager(System *system) : _system(system) {
|
||||||
|
}
|
||||||
|
|
||||||
void showNotification(HistoryItem *item, int forwardedCount) {
|
void showNotification(HistoryItem *item, int forwardedCount) {
|
||||||
doShowNotification(item, forwardedCount);
|
doShowNotification(item, forwardedCount);
|
||||||
}
|
}
|
||||||
|
@ -63,6 +146,10 @@ public:
|
||||||
virtual ~Manager() = default;
|
virtual ~Manager() = default;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
System *system() const {
|
||||||
|
return _system;
|
||||||
|
}
|
||||||
|
|
||||||
virtual void doUpdateAll() = 0;
|
virtual void doUpdateAll() = 0;
|
||||||
virtual void doShowNotification(HistoryItem *item, int forwardedCount) = 0;
|
virtual void doShowNotification(HistoryItem *item, int forwardedCount) = 0;
|
||||||
virtual void doClearAll() = 0;
|
virtual void doClearAll() = 0;
|
||||||
|
@ -74,10 +161,15 @@ protected:
|
||||||
virtual void onAfterNotificationActivated(PeerId peerId, MsgId msgId) {
|
virtual void onAfterNotificationActivated(PeerId peerId, MsgId msgId) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
System *_system = nullptr;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class NativeManager : public Manager {
|
class NativeManager : public Manager {
|
||||||
protected:
|
protected:
|
||||||
|
using Manager::Manager;
|
||||||
|
|
||||||
void doUpdateAll() override {
|
void doUpdateAll() override {
|
||||||
doClearAllFast();
|
doClearAllFast();
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,14 +31,14 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||||
#include "styles/style_dialogs.h"
|
#include "styles/style_dialogs.h"
|
||||||
#include "styles/style_boxes.h"
|
#include "styles/style_boxes.h"
|
||||||
#include "styles/style_window.h"
|
#include "styles/style_window.h"
|
||||||
|
#include "storage/file_download.h"
|
||||||
|
#include "auth_session.h"
|
||||||
|
|
||||||
namespace Window {
|
namespace Window {
|
||||||
namespace Notifications {
|
namespace Notifications {
|
||||||
namespace Default {
|
namespace Default {
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
NeverFreedPointer<Manager> ManagerInstance;
|
|
||||||
|
|
||||||
int notificationMaxHeight() {
|
int notificationMaxHeight() {
|
||||||
return st::notifyMinHeight + st::notifyReplyArea.heightMax + st::notifyBorderWidth;
|
return st::notifyMinHeight + st::notifyReplyArea.heightMax + st::notifyBorderWidth;
|
||||||
}
|
}
|
||||||
|
@ -59,32 +59,24 @@ internal::Widget::Direction notificationShiftDirection() {
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
void Start() {
|
std::unique_ptr<Manager> Create(System *system) {
|
||||||
ManagerInstance.createIfNull();
|
return std::make_unique<Manager>(system);
|
||||||
}
|
}
|
||||||
|
|
||||||
Manager *GetManager() {
|
Manager::Manager(System *system) : Notifications::Manager(system) {
|
||||||
return ManagerInstance.data();
|
subscribe(system->authSession()->downloader()->taskFinished(), [this] {
|
||||||
}
|
for_const (auto ¬ification, _notifications) {
|
||||||
|
|
||||||
void Finish() {
|
|
||||||
ManagerInstance.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
Manager::Manager() {
|
|
||||||
subscribe(FileDownload::ImageLoaded(), [this] {
|
|
||||||
for_const (auto notification, _notifications) {
|
|
||||||
notification->updatePeerPhoto();
|
notification->updatePeerPhoto();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
subscribe(Global::RefNotifySettingsChanged(), [this](Notify::ChangeType change) {
|
subscribe(system->settingsChanged(), [this](ChangeType change) {
|
||||||
settingsChanged(change);
|
settingsChanged(change);
|
||||||
});
|
});
|
||||||
_inputCheckTimer.setTimeoutHandler([this] { checkLastInput(); });
|
_inputCheckTimer.setTimeoutHandler([this] { checkLastInput(); });
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Manager::hasReplyingNotification() const {
|
bool Manager::hasReplyingNotification() const {
|
||||||
for_const (auto notification, _notifications) {
|
for_const (auto ¬ification, _notifications) {
|
||||||
if (notification->isReplying()) {
|
if (notification->isReplying()) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -92,20 +84,20 @@ bool Manager::hasReplyingNotification() const {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Manager::settingsChanged(Notify::ChangeType change) {
|
void Manager::settingsChanged(ChangeType change) {
|
||||||
if (change == Notify::ChangeType::Corner) {
|
if (change == ChangeType::Corner) {
|
||||||
auto startPosition = notificationStartPosition();
|
auto startPosition = notificationStartPosition();
|
||||||
auto shiftDirection = notificationShiftDirection();
|
auto shiftDirection = notificationShiftDirection();
|
||||||
for_const (auto notification, _notifications) {
|
for_const (auto ¬ification, _notifications) {
|
||||||
notification->updatePosition(startPosition, shiftDirection);
|
notification->updatePosition(startPosition, shiftDirection);
|
||||||
}
|
}
|
||||||
if (_hideAll) {
|
if (_hideAll) {
|
||||||
_hideAll->updatePosition(startPosition, shiftDirection);
|
_hideAll->updatePosition(startPosition, shiftDirection);
|
||||||
}
|
}
|
||||||
} else if (change == Notify::ChangeType::MaxCount) {
|
} else if (change == ChangeType::MaxCount) {
|
||||||
int allow = Global::NotificationsCount();
|
int allow = Global::NotificationsCount();
|
||||||
for (int i = _notifications.size(); i != 0;) {
|
for (int i = _notifications.size(); i != 0;) {
|
||||||
auto notification = _notifications[--i];
|
auto ¬ification = _notifications[--i];
|
||||||
if (notification->isUnlinked()) continue;
|
if (notification->isUnlinked()) continue;
|
||||||
if (--allow < 0) {
|
if (--allow < 0) {
|
||||||
notification->unlinkHistory();
|
notification->unlinkHistory();
|
||||||
|
@ -116,14 +108,14 @@ void Manager::settingsChanged(Notify::ChangeType change) {
|
||||||
showNextFromQueue();
|
showNextFromQueue();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (change == Notify::ChangeType::DemoIsShown) {
|
} else if (change == ChangeType::DemoIsShown) {
|
||||||
auto demoIsShown = Global::NotificationsDemoIsShown();
|
auto demoIsShown = Global::NotificationsDemoIsShown();
|
||||||
_demoMasterOpacity.start([this] { demoMasterOpacityCallback(); }, demoIsShown ? 1. : 0., demoIsShown ? 0. : 1., st::notifyFastAnim);
|
_demoMasterOpacity.start([this] { demoMasterOpacityCallback(); }, demoIsShown ? 1. : 0., demoIsShown ? 0. : 1., st::notifyFastAnim);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Manager::demoMasterOpacityCallback() {
|
void Manager::demoMasterOpacityCallback() {
|
||||||
for_const (auto notification, _notifications) {
|
for_const (auto ¬ification, _notifications) {
|
||||||
notification->updateOpacity();
|
notification->updateOpacity();
|
||||||
}
|
}
|
||||||
if (_hideAll) {
|
if (_hideAll) {
|
||||||
|
@ -138,7 +130,7 @@ float64 Manager::demoMasterOpacity() const {
|
||||||
void Manager::checkLastInput() {
|
void Manager::checkLastInput() {
|
||||||
auto replying = hasReplyingNotification();
|
auto replying = hasReplyingNotification();
|
||||||
auto waiting = false;
|
auto waiting = false;
|
||||||
for_const (auto notification, _notifications) {
|
for_const (auto ¬ification, _notifications) {
|
||||||
if (!notification->checkLastInput(replying)) {
|
if (!notification->checkLastInput(replying)) {
|
||||||
waiting = true;
|
waiting = true;
|
||||||
}
|
}
|
||||||
|
@ -151,7 +143,7 @@ void Manager::checkLastInput() {
|
||||||
void Manager::startAllHiding() {
|
void Manager::startAllHiding() {
|
||||||
if (!hasReplyingNotification()) {
|
if (!hasReplyingNotification()) {
|
||||||
int notHidingCount = 0;
|
int notHidingCount = 0;
|
||||||
for_const (auto notification, _notifications) {
|
for_const (auto ¬ification, _notifications) {
|
||||||
if (notification->isShowing()) {
|
if (notification->isShowing()) {
|
||||||
++notHidingCount;
|
++notHidingCount;
|
||||||
} else {
|
} else {
|
||||||
|
@ -166,7 +158,7 @@ void Manager::startAllHiding() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Manager::stopAllHiding() {
|
void Manager::stopAllHiding() {
|
||||||
for_const (auto notification, _notifications) {
|
for_const (auto ¬ification, _notifications) {
|
||||||
notification->stopHiding();
|
notification->stopHiding();
|
||||||
}
|
}
|
||||||
if (_hideAll) {
|
if (_hideAll) {
|
||||||
|
@ -175,46 +167,52 @@ void Manager::stopAllHiding() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Manager::showNextFromQueue() {
|
void Manager::showNextFromQueue() {
|
||||||
if (!_queuedNotifications.isEmpty()) {
|
auto guard = base::scope_guard([this] {
|
||||||
int count = Global::NotificationsCount();
|
if (_positionsOutdated) {
|
||||||
for_const (auto notification, _notifications) {
|
moveWidgets();
|
||||||
if (notification->isUnlinked()) continue;
|
|
||||||
--count;
|
|
||||||
}
|
|
||||||
if (count > 0) {
|
|
||||||
auto startPosition = notificationStartPosition();
|
|
||||||
auto startShift = 0;
|
|
||||||
auto shiftDirection = notificationShiftDirection();
|
|
||||||
do {
|
|
||||||
auto queued = _queuedNotifications.front();
|
|
||||||
_queuedNotifications.pop_front();
|
|
||||||
|
|
||||||
auto notification = std::make_unique<Notification>(
|
|
||||||
queued.history,
|
|
||||||
queued.peer,
|
|
||||||
queued.author,
|
|
||||||
queued.item,
|
|
||||||
queued.forwardedCount,
|
|
||||||
startPosition, startShift, shiftDirection);
|
|
||||||
Platform::Notifications::CustomNotificationShownHook(notification.get());
|
|
||||||
_notifications.push_back(notification.release());
|
|
||||||
--count;
|
|
||||||
} while (count > 0 && !_queuedNotifications.isEmpty());
|
|
||||||
|
|
||||||
_positionsOutdated = true;
|
|
||||||
checkLastInput();
|
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
if (_queuedNotifications.empty()) {
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
if (_positionsOutdated) {
|
int count = Global::NotificationsCount();
|
||||||
moveWidgets();
|
for_const (auto ¬ification, _notifications) {
|
||||||
|
if (notification->isUnlinked()) continue;
|
||||||
|
--count;
|
||||||
}
|
}
|
||||||
|
if (count <= 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto startPosition = notificationStartPosition();
|
||||||
|
auto startShift = 0;
|
||||||
|
auto shiftDirection = notificationShiftDirection();
|
||||||
|
do {
|
||||||
|
auto queued = _queuedNotifications.front();
|
||||||
|
_queuedNotifications.pop_front();
|
||||||
|
|
||||||
|
auto notification = std::make_unique<Notification>(
|
||||||
|
this,
|
||||||
|
queued.history,
|
||||||
|
queued.peer,
|
||||||
|
queued.author,
|
||||||
|
queued.item,
|
||||||
|
queued.forwardedCount,
|
||||||
|
startPosition, startShift, shiftDirection);
|
||||||
|
Platform::Notifications::CustomNotificationShownHook(notification.get());
|
||||||
|
_notifications.push_back(std::move(notification));
|
||||||
|
--count;
|
||||||
|
} while (count > 0 && !_queuedNotifications.empty());
|
||||||
|
|
||||||
|
_positionsOutdated = true;
|
||||||
|
checkLastInput();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Manager::moveWidgets() {
|
void Manager::moveWidgets() {
|
||||||
auto shift = st::notifyDeltaY;
|
auto shift = st::notifyDeltaY;
|
||||||
int lastShift = 0, lastShiftCurrent = 0, count = 0;
|
int lastShift = 0, lastShiftCurrent = 0, count = 0;
|
||||||
for (int i = _notifications.size(); i != 0;) {
|
for (int i = _notifications.size(); i != 0;) {
|
||||||
auto notification = _notifications[--i];
|
auto ¬ification = _notifications[--i];
|
||||||
if (notification->isUnlinked()) continue;
|
if (notification->isUnlinked()) continue;
|
||||||
|
|
||||||
notification->changeShift(shift);
|
notification->changeShift(shift);
|
||||||
|
@ -226,10 +224,10 @@ void Manager::moveWidgets() {
|
||||||
++count;
|
++count;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (count > 1 || !_queuedNotifications.isEmpty()) {
|
if (count > 1 || !_queuedNotifications.empty()) {
|
||||||
auto deltaY = st::notifyHideAllHeight + st::notifyDeltaY;
|
auto deltaY = st::notifyHideAllHeight + st::notifyDeltaY;
|
||||||
if (!_hideAll) {
|
if (!_hideAll) {
|
||||||
_hideAll = new HideAllButton(notificationStartPosition(), lastShiftCurrent, notificationShiftDirection());
|
_hideAll = std::make_unique<HideAllButton>(this, notificationStartPosition(), lastShiftCurrent, notificationShiftDirection());
|
||||||
}
|
}
|
||||||
_hideAll->changeShift(lastShift);
|
_hideAll->changeShift(lastShift);
|
||||||
_hideAll->stopHiding();
|
_hideAll->stopHiding();
|
||||||
|
@ -243,10 +241,12 @@ void Manager::changeNotificationHeight(Notification *notification, int newHeight
|
||||||
if (!deltaHeight) return;
|
if (!deltaHeight) return;
|
||||||
|
|
||||||
notification->addToHeight(deltaHeight);
|
notification->addToHeight(deltaHeight);
|
||||||
auto index = _notifications.indexOf(notification);
|
auto it = std::find_if(_notifications.cbegin(), _notifications.cend(), [notification](auto &item) {
|
||||||
if (index > 0) {
|
return (item.get() == notification);
|
||||||
for (int i = 0; i != index; ++i) {
|
});
|
||||||
auto notification = _notifications[i];
|
if (it != _notifications.cend()) {
|
||||||
|
for (auto i = _notifications.cbegin(); i != it; ++i) {
|
||||||
|
auto ¬ification = *i;
|
||||||
if (notification->isUnlinked()) continue;
|
if (notification->isUnlinked()) continue;
|
||||||
|
|
||||||
notification->addToShift(deltaHeight);
|
notification->addToShift(deltaHeight);
|
||||||
|
@ -266,22 +266,21 @@ void Manager::unlinkFromShown(Notification *remove) {
|
||||||
showNextFromQueue();
|
showNextFromQueue();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Manager::removeFromShown(Notification *remove) {
|
void Manager::removeWidget(internal::Widget *remove) {
|
||||||
if (remove) {
|
if (remove == _hideAll.get()) {
|
||||||
auto index = _notifications.indexOf(remove);
|
_hideAll.reset();
|
||||||
if (index >= 0) {
|
} else if (remove) {
|
||||||
_notifications.removeAt(index);
|
auto it = std::find_if(_notifications.cbegin(), _notifications.cend(), [remove](auto &item) {
|
||||||
|
return item.get() == remove;
|
||||||
|
});
|
||||||
|
if (it != _notifications.cend()) {
|
||||||
|
_notifications.erase(it);
|
||||||
_positionsOutdated = true;
|
_positionsOutdated = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
showNextFromQueue();
|
showNextFromQueue();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Manager::removeHideAll(HideAllButton *remove) {
|
|
||||||
if (remove == _hideAll) {
|
|
||||||
_hideAll = nullptr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
void Manager::doShowNotification(HistoryItem *item, int forwardedCount) {
|
void Manager::doShowNotification(HistoryItem *item, int forwardedCount) {
|
||||||
_queuedNotifications.push_back(QueuedNotification(item, forwardedCount));
|
_queuedNotifications.push_back(QueuedNotification(item, forwardedCount));
|
||||||
showNextFromQueue();
|
showNextFromQueue();
|
||||||
|
@ -289,7 +288,7 @@ void Manager::doShowNotification(HistoryItem *item, int forwardedCount) {
|
||||||
|
|
||||||
void Manager::doClearAll() {
|
void Manager::doClearAll() {
|
||||||
_queuedNotifications.clear();
|
_queuedNotifications.clear();
|
||||||
for_const (auto notification, _notifications) {
|
for_const (auto ¬ification, _notifications) {
|
||||||
notification->unlinkHistory();
|
notification->unlinkHistory();
|
||||||
}
|
}
|
||||||
showNextFromQueue();
|
showNextFromQueue();
|
||||||
|
@ -297,11 +296,8 @@ void Manager::doClearAll() {
|
||||||
|
|
||||||
void Manager::doClearAllFast() {
|
void Manager::doClearAllFast() {
|
||||||
_queuedNotifications.clear();
|
_queuedNotifications.clear();
|
||||||
auto notifications = base::take(_notifications);
|
base::take(_notifications);
|
||||||
for_const (auto notification, notifications) {
|
base::take(_hideAll);
|
||||||
delete notification;
|
|
||||||
}
|
|
||||||
delete base::take(_hideAll);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Manager::doClearFromHistory(History *history) {
|
void Manager::doClearFromHistory(History *history) {
|
||||||
|
@ -312,7 +308,7 @@ void Manager::doClearFromHistory(History *history) {
|
||||||
++i;
|
++i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for_const (auto notification, _notifications) {
|
for_const (auto ¬ification, _notifications) {
|
||||||
if (notification->unlinkHistory(history)) {
|
if (notification->unlinkHistory(history)) {
|
||||||
_positionsOutdated = true;
|
_positionsOutdated = true;
|
||||||
}
|
}
|
||||||
|
@ -321,20 +317,18 @@ void Manager::doClearFromHistory(History *history) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Manager::doClearFromItem(HistoryItem *item) {
|
void Manager::doClearFromItem(HistoryItem *item) {
|
||||||
for (auto i = 0, queuedCount = _queuedNotifications.size(); i != queuedCount; ++i) {
|
_queuedNotifications.erase(std::remove_if(_queuedNotifications.begin(), _queuedNotifications.end(), [item](auto &queued) {
|
||||||
if (_queuedNotifications[i].item == item) {
|
return (queued.item == item);
|
||||||
_queuedNotifications.removeAt(i);
|
}), _queuedNotifications.cend());
|
||||||
break;
|
|
||||||
}
|
for_const (auto ¬ification, _notifications) {
|
||||||
}
|
|
||||||
for_const (auto notification, _notifications) {
|
|
||||||
// Calls unlinkFromShown() -> showNextFromQueue()
|
// Calls unlinkFromShown() -> showNextFromQueue()
|
||||||
notification->itemRemoved(item);
|
notification->itemRemoved(item);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Manager::doUpdateAll() {
|
void Manager::doUpdateAll() {
|
||||||
for_const (auto notification, _notifications) {
|
for_const (auto ¬ification, _notifications) {
|
||||||
notification->updateNotifyDisplay();
|
notification->updateNotifyDisplay();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -345,7 +339,8 @@ Manager::~Manager() {
|
||||||
|
|
||||||
namespace internal {
|
namespace internal {
|
||||||
|
|
||||||
Widget::Widget(QPoint startPosition, int shift, Direction shiftDirection) : TWidget(nullptr)
|
Widget::Widget(Manager *manager, QPoint startPosition, int shift, Direction shiftDirection) : TWidget(nullptr)
|
||||||
|
, _manager(manager)
|
||||||
, _startPosition(startPosition)
|
, _startPosition(startPosition)
|
||||||
, _direction(shiftDirection)
|
, _direction(shiftDirection)
|
||||||
, a_shift(shift)
|
, a_shift(shift)
|
||||||
|
@ -364,12 +359,10 @@ void Widget::destroyDelayed() {
|
||||||
if (_deleted) return;
|
if (_deleted) return;
|
||||||
_deleted = true;
|
_deleted = true;
|
||||||
|
|
||||||
// Ubuntu has a lag if deleteLater() called immediately.
|
// Ubuntu has a lag if a fully transparent widget is destroyed immediately.
|
||||||
#if defined Q_OS_LINUX32 || defined Q_OS_LINUX64
|
App::CallDelayed(1000, this, [this] {
|
||||||
QTimer::singleShot(1000, [this] { delete this; });
|
manager()->removeWidget(this);
|
||||||
#else // Q_OS_LINUX32 || Q_OS_LINUX64
|
});
|
||||||
deleteLater();
|
|
||||||
#endif // Q_OS_LINUX32 || Q_OS_LINUX64
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Widget::opacityAnimationCallback() {
|
void Widget::opacityAnimationCallback() {
|
||||||
|
@ -411,9 +404,7 @@ void Widget::hideAnimated(float64 duration, const anim::transition &func) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Widget::updateOpacity() {
|
void Widget::updateOpacity() {
|
||||||
if (auto manager = ManagerInstance.data()) {
|
setWindowOpacity(_a_opacity.current(_hiding ? 0. : 1.) * _manager->demoMasterOpacity());
|
||||||
setWindowOpacity(_a_opacity.current(_hiding ? 0. : 1.) * manager->demoMasterOpacity());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Widget::changeShift(int top) {
|
void Widget::changeShift(int top) {
|
||||||
|
@ -469,7 +460,7 @@ void Background::paintEvent(QPaintEvent *e) {
|
||||||
p.fillRect(st::notifyBorderWidth, height() - st::notifyBorderWidth, width() - 2 * st::notifyBorderWidth, st::notifyBorderWidth, st::notifyBorder);
|
p.fillRect(st::notifyBorderWidth, height() - st::notifyBorderWidth, width() - 2 * st::notifyBorderWidth, st::notifyBorderWidth, st::notifyBorder);
|
||||||
}
|
}
|
||||||
|
|
||||||
Notification::Notification(History *history, PeerData *peer, PeerData *author, HistoryItem *msg, int forwardedCount, QPoint startPosition, int shift, Direction shiftDirection) : Widget(startPosition, shift, shiftDirection)
|
Notification::Notification(Manager *manager, History *history, PeerData *peer, PeerData *author, HistoryItem *msg, int forwardedCount, QPoint startPosition, int shift, Direction shiftDirection) : Widget(manager, startPosition, shift, shiftDirection)
|
||||||
, _history(history)
|
, _history(history)
|
||||||
, _peer(peer)
|
, _peer(peer)
|
||||||
, _author(author)
|
, _author(author)
|
||||||
|
@ -711,9 +702,7 @@ bool Notification::canReply() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Notification::unlinkHistoryInManager() {
|
void Notification::unlinkHistoryInManager() {
|
||||||
if (auto manager = ManagerInstance.data()) {
|
manager()->unlinkFromShown(this);
|
||||||
manager->unlinkFromShown(this);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Notification::toggleActionButtons(bool visible) {
|
void Notification::toggleActionButtons(bool visible) {
|
||||||
|
@ -766,19 +755,15 @@ void Notification::showReplyField() {
|
||||||
void Notification::sendReply() {
|
void Notification::sendReply() {
|
||||||
if (!_history) return;
|
if (!_history) return;
|
||||||
|
|
||||||
if (auto manager = ManagerInstance.data()) {
|
auto peerId = _history->peer->id;
|
||||||
auto peerId = _history->peer->id;
|
auto msgId = _item ? _item->id : ShowAtUnreadMsgId;
|
||||||
auto msgId = _item ? _item->id : ShowAtUnreadMsgId;
|
manager()->notificationReplied(peerId, msgId, _replyArea->getLastText());
|
||||||
manager->notificationReplied(peerId, msgId, _replyArea->getLastText());
|
|
||||||
|
|
||||||
manager->startAllHiding();
|
manager()->startAllHiding();
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Notification::changeHeight(int newHeight) {
|
void Notification::changeHeight(int newHeight) {
|
||||||
if (auto manager = ManagerInstance.data()) {
|
manager()->changeNotificationHeight(this, newHeight);
|
||||||
manager->changeNotificationHeight(this, newHeight);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Notification::unlinkHistory(History *history) {
|
bool Notification::unlinkHistory(History *history) {
|
||||||
|
@ -793,9 +778,7 @@ bool Notification::unlinkHistory(History *history) {
|
||||||
|
|
||||||
void Notification::enterEventHook(QEvent *e) {
|
void Notification::enterEventHook(QEvent *e) {
|
||||||
if (!_history) return;
|
if (!_history) return;
|
||||||
if (auto manager = ManagerInstance.data()) {
|
manager()->stopAllHiding();
|
||||||
manager->stopAllHiding();
|
|
||||||
}
|
|
||||||
if (!_replyArea && canReply()) {
|
if (!_replyArea && canReply()) {
|
||||||
toggleActionButtons(true);
|
toggleActionButtons(true);
|
||||||
}
|
}
|
||||||
|
@ -803,9 +786,7 @@ void Notification::enterEventHook(QEvent *e) {
|
||||||
|
|
||||||
void Notification::leaveEventHook(QEvent *e) {
|
void Notification::leaveEventHook(QEvent *e) {
|
||||||
if (!_history) return;
|
if (!_history) return;
|
||||||
if (auto manager = ManagerInstance.data()) {
|
manager()->startAllHiding();
|
||||||
manager->startAllHiding();
|
|
||||||
}
|
|
||||||
toggleActionButtons(false);
|
toggleActionButtons(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -821,11 +802,9 @@ void Notification::mousePressEvent(QMouseEvent *e) {
|
||||||
unlinkHistoryInManager();
|
unlinkHistoryInManager();
|
||||||
} else {
|
} else {
|
||||||
e->ignore();
|
e->ignore();
|
||||||
if (auto manager = ManagerInstance.data()) {
|
auto peerId = _history->peer->id;
|
||||||
auto peerId = _history->peer->id;
|
auto msgId = _item ? _item->id : ShowAtUnreadMsgId;
|
||||||
auto msgId = _item ? _item->id : ShowAtUnreadMsgId;
|
manager()->notificationActivated(peerId, msgId);
|
||||||
manager->notificationActivated(peerId, msgId);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -850,13 +829,7 @@ void Notification::onHideByTimer() {
|
||||||
startHiding();
|
startHiding();
|
||||||
}
|
}
|
||||||
|
|
||||||
Notification::~Notification() {
|
HideAllButton::HideAllButton(Manager *manager, QPoint startPosition, int shift, Direction shiftDirection) : Widget(manager, startPosition, shift, shiftDirection) {
|
||||||
if (auto manager = ManagerInstance.data()) {
|
|
||||||
manager->removeFromShown(this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
HideAllButton::HideAllButton(QPoint startPosition, int shift, Direction shiftDirection) : Widget(startPosition, shift, shiftDirection) {
|
|
||||||
setCursor(style::cur_pointer);
|
setCursor(style::cur_pointer);
|
||||||
|
|
||||||
auto position = computePosition(st::notifyHideAllHeight);
|
auto position = computePosition(st::notifyHideAllHeight);
|
||||||
|
@ -885,12 +858,6 @@ void HideAllButton::stopHiding() {
|
||||||
hideStop();
|
hideStop();
|
||||||
}
|
}
|
||||||
|
|
||||||
HideAllButton::~HideAllButton() {
|
|
||||||
if (auto manager = ManagerInstance.data()) {
|
|
||||||
manager->removeHideAll(this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void HideAllButton::enterEventHook(QEvent *e) {
|
void HideAllButton::enterEventHook(QEvent *e) {
|
||||||
_mouseOver = true;
|
_mouseOver = true;
|
||||||
update();
|
update();
|
||||||
|
@ -908,9 +875,7 @@ void HideAllButton::mousePressEvent(QMouseEvent *e) {
|
||||||
void HideAllButton::mouseReleaseEvent(QMouseEvent *e) {
|
void HideAllButton::mouseReleaseEvent(QMouseEvent *e) {
|
||||||
auto mouseDown = base::take(_mouseDown);
|
auto mouseDown = base::take(_mouseDown);
|
||||||
if (mouseDown && _mouseOver) {
|
if (mouseDown && _mouseOver) {
|
||||||
if (auto manager = ManagerInstance.data()) {
|
manager()->clearAll();
|
||||||
manager->clearAll();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -39,18 +39,15 @@ class HideAllButton;
|
||||||
} // namespace internal
|
} // namespace internal
|
||||||
|
|
||||||
class Manager;
|
class Manager;
|
||||||
|
std::unique_ptr<Manager> Create(System *system);
|
||||||
void Start();
|
|
||||||
Manager *GetManager();
|
|
||||||
void Finish();
|
|
||||||
|
|
||||||
class Manager : public Notifications::Manager, private base::Subscriber {
|
class Manager : public Notifications::Manager, private base::Subscriber {
|
||||||
public:
|
public:
|
||||||
Manager();
|
Manager(System *system);
|
||||||
|
|
||||||
template <typename Method>
|
template <typename Method>
|
||||||
void enumerateNotifications(Method method) {
|
void enumerateNotifications(Method method) {
|
||||||
for_const (auto notification, _notifications) {
|
for_const (auto ¬ification, _notifications) {
|
||||||
method(notification);
|
method(notification);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -73,25 +70,24 @@ private:
|
||||||
|
|
||||||
void showNextFromQueue();
|
void showNextFromQueue();
|
||||||
void unlinkFromShown(Notification *remove);
|
void unlinkFromShown(Notification *remove);
|
||||||
void removeFromShown(Notification *remove);
|
|
||||||
void removeHideAll(HideAllButton *remove);
|
|
||||||
void startAllHiding();
|
void startAllHiding();
|
||||||
void stopAllHiding();
|
void stopAllHiding();
|
||||||
void checkLastInput();
|
void checkLastInput();
|
||||||
|
|
||||||
|
void removeWidget(internal::Widget *remove);
|
||||||
|
|
||||||
float64 demoMasterOpacity() const;
|
float64 demoMasterOpacity() const;
|
||||||
void demoMasterOpacityCallback();
|
void demoMasterOpacityCallback();
|
||||||
|
|
||||||
void moveWidgets();
|
void moveWidgets();
|
||||||
void changeNotificationHeight(Notification *widget, int newHeight);
|
void changeNotificationHeight(Notification *widget, int newHeight);
|
||||||
void settingsChanged(Notify::ChangeType change);
|
void settingsChanged(ChangeType change);
|
||||||
|
|
||||||
bool hasReplyingNotification() const;
|
bool hasReplyingNotification() const;
|
||||||
|
|
||||||
using Notifications = QList<Notification*>;
|
std::vector<std::unique_ptr<Notification>> _notifications;
|
||||||
Notifications _notifications;
|
|
||||||
|
|
||||||
HideAllButton *_hideAll = nullptr;
|
std::unique_ptr<HideAllButton> _hideAll;
|
||||||
|
|
||||||
bool _positionsOutdated = false;
|
bool _positionsOutdated = false;
|
||||||
SingleTimer _inputCheckTimer;
|
SingleTimer _inputCheckTimer;
|
||||||
|
@ -111,8 +107,7 @@ private:
|
||||||
HistoryItem *item;
|
HistoryItem *item;
|
||||||
int forwardedCount;
|
int forwardedCount;
|
||||||
};
|
};
|
||||||
using QueuedNotifications = QList<QueuedNotification>;
|
std::deque<QueuedNotification> _queuedNotifications;
|
||||||
QueuedNotifications _queuedNotifications;
|
|
||||||
|
|
||||||
Animation _demoMasterOpacity;
|
Animation _demoMasterOpacity;
|
||||||
|
|
||||||
|
@ -126,7 +121,7 @@ public:
|
||||||
Up,
|
Up,
|
||||||
Down,
|
Down,
|
||||||
};
|
};
|
||||||
Widget(QPoint startPosition, int shift, Direction shiftDirection);
|
Widget(Manager *manager, QPoint startPosition, int shift, Direction shiftDirection);
|
||||||
|
|
||||||
bool isShowing() const {
|
bool isShowing() const {
|
||||||
return _a_opacity.animating() && !_hiding;
|
return _a_opacity.animating() && !_hiding;
|
||||||
|
@ -149,6 +144,11 @@ protected:
|
||||||
|
|
||||||
virtual void updateGeometry(int x, int y, int width, int height);
|
virtual void updateGeometry(int x, int y, int width, int height);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
Manager *manager() const {
|
||||||
|
return _manager;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void opacityAnimationCallback();
|
void opacityAnimationCallback();
|
||||||
void destroyDelayed();
|
void destroyDelayed();
|
||||||
|
@ -156,6 +156,8 @@ private:
|
||||||
void hideAnimated(float64 duration, const anim::transition &func);
|
void hideAnimated(float64 duration, const anim::transition &func);
|
||||||
void step_shift(float64 ms, bool timer);
|
void step_shift(float64 ms, bool timer);
|
||||||
|
|
||||||
|
Manager *_manager = nullptr;
|
||||||
|
|
||||||
bool _hiding = false;
|
bool _hiding = false;
|
||||||
bool _deleted = false;
|
bool _deleted = false;
|
||||||
Animation _a_opacity;
|
Animation _a_opacity;
|
||||||
|
@ -180,7 +182,7 @@ class Notification : public Widget {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Notification(History *history, PeerData *peer, PeerData *author, HistoryItem *item, int forwardedCount, QPoint startPosition, int shift, Direction shiftDirection);
|
Notification(Manager *manager, History *history, PeerData *peer, PeerData *author, HistoryItem *item, int forwardedCount, QPoint startPosition, int shift, Direction shiftDirection);
|
||||||
|
|
||||||
void startHiding();
|
void startHiding();
|
||||||
void stopHiding();
|
void stopHiding();
|
||||||
|
@ -200,8 +202,6 @@ public:
|
||||||
bool unlinkHistory(History *history = nullptr);
|
bool unlinkHistory(History *history = nullptr);
|
||||||
bool checkLastInput(bool hasReplyingNotifications);
|
bool checkLastInput(bool hasReplyingNotifications);
|
||||||
|
|
||||||
~Notification();
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void enterEventHook(QEvent *e) override;
|
void enterEventHook(QEvent *e) override;
|
||||||
void leaveEventHook(QEvent *e) override;
|
void leaveEventHook(QEvent *e) override;
|
||||||
|
@ -260,14 +260,12 @@ private:
|
||||||
|
|
||||||
class HideAllButton : public Widget {
|
class HideAllButton : public Widget {
|
||||||
public:
|
public:
|
||||||
HideAllButton(QPoint startPosition, int shift, Direction shiftDirection);
|
HideAllButton(Manager *manager, QPoint startPosition, int shift, Direction shiftDirection);
|
||||||
|
|
||||||
void startHiding();
|
void startHiding();
|
||||||
void startHidingFast();
|
void startHidingFast();
|
||||||
void stopHiding();
|
void stopHiding();
|
||||||
|
|
||||||
~HideAllButton();
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void enterEventHook(QEvent *e) override;
|
void enterEventHook(QEvent *e) override;
|
||||||
void leaveEventHook(QEvent *e) override;
|
void leaveEventHook(QEvent *e) override;
|
||||||
|
|
|
@ -112,7 +112,13 @@ void CachedUserpics::onClear() {
|
||||||
|
|
||||||
CachedUserpics::~CachedUserpics() {
|
CachedUserpics::~CachedUserpics() {
|
||||||
if (_someSavedFlag) {
|
if (_someSavedFlag) {
|
||||||
psDeleteDir(cWorkingDir() + qsl("tdata/temp"));
|
TimeMs result = 0;
|
||||||
|
for_const (auto &item, _images) {
|
||||||
|
QFile(item.path).remove();
|
||||||
|
}
|
||||||
|
|
||||||
|
// This works about 1200ms on Windows for a folder with one image O_o
|
||||||
|
// psDeleteDir(cWorkingDir() + qsl("tdata/temp"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -30,6 +30,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||||
#include "boxes/aboutbox.h"
|
#include "boxes/aboutbox.h"
|
||||||
#include "lang.h"
|
#include "lang.h"
|
||||||
#include "core/click_handler_types.h"
|
#include "core/click_handler_types.h"
|
||||||
|
#include "auth_session.h"
|
||||||
|
|
||||||
namespace Window {
|
namespace Window {
|
||||||
|
|
||||||
|
@ -70,7 +71,7 @@ MainMenu::MainMenu(QWidget *parent) : TWidget(parent)
|
||||||
_version->setLink(1, MakeShared<UrlClickHandler>(qsl("https://desktop.telegram.org/changelog")));
|
_version->setLink(1, MakeShared<UrlClickHandler>(qsl("https://desktop.telegram.org/changelog")));
|
||||||
_version->setLink(2, MakeShared<LambdaClickHandler>([] { Ui::show(Box<AboutBox>()); }));
|
_version->setLink(2, MakeShared<LambdaClickHandler>([] { Ui::show(Box<AboutBox>()); }));
|
||||||
|
|
||||||
subscribe(FileDownload::ImageLoaded(), [this] { update(); });
|
subscribe(AuthSession::CurrentDownloaderTaskFinished(), [this] { update(); });
|
||||||
subscribe(Global::RefConnectionTypeChanged(), [this] { updateConnectionState(); });
|
subscribe(Global::RefConnectionTypeChanged(), [this] { updateConnectionState(); });
|
||||||
updateConnectionState();
|
updateConnectionState();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue