From 31a847fb9d43174168eac39bd8a104f5127dbd42 Mon Sep 17 00:00:00 2001 From: John Preston Date: Fri, 14 Oct 2016 20:10:15 +0300 Subject: [PATCH] Playlist appearance added to the new media player. Also itemRemoved() now is fired as a global observable. --- Telegram/Resources/icons/playlist_shadow.png | Bin 0 -> 75 bytes .../Resources/icons/playlist_shadow@2x.png | Bin 0 -> 91 bytes Telegram/SourceFiles/app.cpp | 4 +- Telegram/SourceFiles/core/observer.h | 35 +++- Telegram/SourceFiles/core/stl_subset.h | 13 ++ Telegram/SourceFiles/core/type_traits.h | 102 ++++++++++ Telegram/SourceFiles/dialogswidget.cpp | 7 +- Telegram/SourceFiles/dialogswidget.h | 8 +- Telegram/SourceFiles/facades.cpp | 4 + Telegram/SourceFiles/facades.h | 8 + Telegram/SourceFiles/historywidget.cpp | 15 +- Telegram/SourceFiles/historywidget.h | 13 +- Telegram/SourceFiles/mainwidget.cpp | 161 +++++++++++----- Telegram/SourceFiles/mainwidget.h | 13 +- Telegram/SourceFiles/mainwindow.cpp | 2 +- .../media/player/media_player.style | 9 +- .../media/player/media_player_cover.cpp | 5 +- .../media/player/media_player_instance.h | 22 +-- .../media/player/media_player_list.cpp | 25 +++ .../media/player/media_player_list.h | 4 +- .../media/player/media_player_panel.cpp | 180 ++++++++++++------ .../media/player/media_player_panel.h | 41 ++-- .../player/media_player_title_button.cpp | 14 ++ .../media/player/media_player_title_button.h | 2 + .../media/player/media_player_widget.cpp | 51 ++++- .../media/player/media_player_widget.h | 9 + .../media/view/media_clip_playback.cpp | 6 +- Telegram/SourceFiles/overview/overview.style | 15 ++ .../SourceFiles/overview/overview_layout.cpp | 12 +- Telegram/SourceFiles/overviewwidget.cpp | 57 ++---- Telegram/SourceFiles/overviewwidget.h | 71 ++++--- .../settings_notifications_widget.cpp | 2 +- Telegram/SourceFiles/title.cpp | 23 ++- Telegram/SourceFiles/title.h | 2 +- .../ui/widgets/continuous_slider.h | 6 +- .../window/notifications_manager_default.cpp | 4 +- .../window/notifications_manager_default.h | 2 +- Telegram/gyp/Telegram.gyp | 1 + 38 files changed, 677 insertions(+), 271 deletions(-) create mode 100644 Telegram/Resources/icons/playlist_shadow.png create mode 100644 Telegram/Resources/icons/playlist_shadow@2x.png create mode 100644 Telegram/SourceFiles/core/type_traits.h diff --git a/Telegram/Resources/icons/playlist_shadow.png b/Telegram/Resources/icons/playlist_shadow.png new file mode 100644 index 0000000000000000000000000000000000000000..606ddfb51f7aaf0f2c476a76c735da8e9a5b56d5 GIT binary patch literal 75 zcmeAS@N?(olHy`uVBq!ia0vp^j6lr9!3HE}Hf~b~QbL|Cjv*W~lP64{{{Q@eqes8W ZGjO>wRk0lix&@SF@O1TaS?83{1OQpd6Sn{W literal 0 HcmV?d00001 diff --git a/Telegram/Resources/icons/playlist_shadow@2x.png b/Telegram/Resources/icons/playlist_shadow@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..dc433eb82157c97e08b4f03db140af013adc48b1 GIT binary patch literal 91 zcmeAS@N?(olHy`uVBq!ia0vp^OhC-S!3HFkynkm2q?9~e978x}vL4*X3zT8l;PvCk o|N9#+xs}U5dDk>YQXsVS!>Yv`t_8K_NkG*Mp00i_>zopr0Q@u?F#rGn literal 0 HcmV?d00001 diff --git a/Telegram/SourceFiles/app.cpp b/Telegram/SourceFiles/app.cpp index 48a385a0b..726f7c857 100644 --- a/Telegram/SourceFiles/app.cpp +++ b/Telegram/SourceFiles/app.cpp @@ -2018,8 +2018,8 @@ namespace { if (auto manager = Window::Notifications::manager()) { manager->clearFromItem(item); } - if (App::main() && !App::quitting()) { - App::main()->itemRemoved(item); + if (Global::started() && !App::quitting()) { + Global::RefItemRemoved().notify(item, true); } } diff --git a/Telegram/SourceFiles/core/observer.h b/Telegram/SourceFiles/core/observer.h index d07189309..ea3431623 100644 --- a/Telegram/SourceFiles/core/observer.h +++ b/Telegram/SourceFiles/core/observer.h @@ -21,6 +21,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org #pragma once #include "core/vector_of_moveable.h" +#include "core/type_traits.h" namespace base { namespace internal { @@ -30,9 +31,12 @@ void RegisterPendingObservable(ObservableCallHandlers *handlers); void UnregisterActiveObservable(ObservableCallHandlers *handlers); void UnregisterObservable(ObservableCallHandlers *handlers); +template +using EventParamType = typename base::type_traits::parameter_type; + template struct SubscriptionHandlerHelper { - using type = base::lambda_unique; + using type = base::lambda_unique)>; }; template <> @@ -67,6 +71,9 @@ public: qSwap(_removeMethod, other._removeMethod); return *this; } + explicit operator bool() const { + return (_node != nullptr); + } void destroy() { if (_node) { (*_removeMethod)(_node); @@ -128,14 +135,26 @@ private: template > class Observable : public internal::CommonObservable { + using SimpleEventType = typename base::type_traits::is_fast_copy_type; + public: + template > void notify(EventType &&event, bool sync = false) { if (this->_data) { this->_data->notify(std_::move(event), sync); } } + template > void notify(const EventType &event, bool sync = false) { - notify(EventType(event)); + if (this->_data) { + this->_data->notify(EventType(event), sync); + } + } + template > + void notify(EventType event, bool sync = false) { + if (this->_data) { + this->_data->notify(std_::move(event), sync); + } } }; @@ -338,7 +357,7 @@ protected: template int subscribe(base::Observable &observable, Lambda &&handler) { _subscriptions.push_back(observable.add_subscription(std_::forward(handler))); - return _subscriptions.size() - 1; + return _subscriptions.size(); } template @@ -347,8 +366,14 @@ protected: } void unsubscribe(int index) { - t_assert(index >= 0 && index < _subscriptions.size()); - _subscriptions[index].destroy(); + if (!index) return; + t_assert(index > 0 && index <= _subscriptions.size()); + _subscriptions[index - 1].destroy(); + if (index == _subscriptions.size()) { + while (index > 0 && !_subscriptions[--index]) { + _subscriptions.pop_back(); + } + } } ~Subscriber() { diff --git a/Telegram/SourceFiles/core/stl_subset.h b/Telegram/SourceFiles/core/stl_subset.h index 9c7747616..26596b22b 100644 --- a/Telegram/SourceFiles/core/stl_subset.h +++ b/Telegram/SourceFiles/core/stl_subset.h @@ -139,6 +139,19 @@ struct enable_if { template using enable_if_t = typename enable_if::type; +template +struct conditional { + using type = Second; +}; + +template +struct conditional { + using type = First; +}; + +template +using conditional_t = typename conditional::type; + template struct add_const { using type = const T; diff --git a/Telegram/SourceFiles/core/type_traits.h b/Telegram/SourceFiles/core/type_traits.h new file mode 100644 index 000000000..62effcaa7 --- /dev/null +++ b/Telegram/SourceFiles/core/type_traits.h @@ -0,0 +1,102 @@ +/* +This file is part of Telegram Desktop, +the official desktop version of Telegram messaging app, see https://telegram.org + +Telegram Desktop is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +It is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +In addition, as a special exception, the copyright holders give permission +to link the code of portions of this program with the OpenSSL library. + +Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE +Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org +*/ +#pragma once + +#include "core/stl_subset.h" + +namespace base { + +template +struct custom_is_fast_copy_type : public std_::false_type { +}; +// To make your own type a fast copy type just write: +// template <> +// struct base::custom_is_fast_copy_type : public std_::true_type { +// }; + +namespace internal { + +template +struct type_list_contains; + +template +struct type_list_contains : public std_::false_type { +}; + +template +struct type_list_contains : public std_::integral_constant::value || type_list_contains::value> { +}; + +template +using is_std_unsigned_int = type_list_contains; + +template +using is_std_signed_int = type_list_contains; + +template +using is_std_integral = std_::integral_constant::value || is_std_signed_int::value || type_list_contains::value>; + +template +using is_std_float = type_list_contains; + +template +using is_std_arith = std_::integral_constant::value || is_std_float::value>; + +template +using is_std_fundamental = std_::integral_constant::value || std_::is_same::value>; + +template +struct is_pointer : public std_::false_type { +}; + +template +struct is_pointer : public std_::true_type { +}; + +template +struct is_member_pointer : public std_::false_type { +}; + +template +struct is_member_pointer : public std_::true_type { +}; + +template +using is_fast_copy_type = std_::integral_constant::value || is_pointer::value || is_member_pointer::value || custom_is_fast_copy_type::value>; + +} // namespace internal + +template +struct type_traits { + using is_std_unsigned_int = internal::is_std_unsigned_int; + using is_std_signed_int = internal::is_std_signed_int; + using is_std_integral = internal::is_std_integral; + using is_std_float = internal::is_std_float; + using is_std_arith = internal::is_std_arith; + using is_std_fundamental = internal::is_std_fundamental; + using is_pointer = internal::is_pointer; + using is_member_pointer = internal::is_member_pointer; + using is_fast_copy_type = internal::is_fast_copy_type; + + using parameter_type = std_::conditional_t; +}; + +} // namespace base diff --git a/Telegram/SourceFiles/dialogswidget.cpp b/Telegram/SourceFiles/dialogswidget.cpp index 66778d0f8..c42a019ff 100644 --- a/Telegram/SourceFiles/dialogswidget.cpp +++ b/Telegram/SourceFiles/dialogswidget.cpp @@ -55,6 +55,9 @@ DialogsInner::DialogsInner(QWidget *parent, MainWidget *main) : SplittedWidget(p _cancelSearchInPeer.hide(); subscribe(FileDownload::ImageLoaded(), [this] { update(); }); + subscribe(Global::RefItemRemoved(), [this](HistoryItem *item) { + itemRemoved(item); + }); refresh(); } @@ -1900,10 +1903,6 @@ void DialogsWidget::onCancel() { } } -void DialogsWidget::itemRemoved(HistoryItem *item) { - _inner.itemRemoved(item); -} - void DialogsWidget::updateNotifySettings(PeerData *peer) { _inner.updateNotifySettings(peer); } diff --git a/Telegram/SourceFiles/dialogswidget.h b/Telegram/SourceFiles/dialogswidget.h index 78ed3d010..7a6631c4f 100644 --- a/Telegram/SourceFiles/dialogswidget.h +++ b/Telegram/SourceFiles/dialogswidget.h @@ -48,7 +48,6 @@ class DialogsInner : public SplittedWidget, public RPCSender, private base::Subs Q_OBJECT public: - DialogsInner(QWidget *parent, MainWidget *main); void dialogsReceived(const QVector &dialogs); @@ -119,7 +118,6 @@ public: void onFilterUpdate(QString newFilter, bool force = false); void onHashtagFilterUpdate(QStringRef newFilter); - void itemRemoved(HistoryItem *item); PeerData *updateFromParentDrag(QPoint globalPos); @@ -131,7 +129,6 @@ public: ~DialogsInner(); public slots: - void onUpdateSelected(bool force = false); void onParentGeometryChanged(); void onPeerNameChanged(PeerData *peer, const PeerData::Names &oldNames, const PeerData::NameFirstChars &oldChars); @@ -152,7 +149,6 @@ public slots: void peerUpdated(PeerData *peer); signals: - void mustScrollTo(int scrollToTop, int scrollToBottom); void dialogMoved(int movedFrom, int movedTo); void searchMessages(); @@ -162,10 +158,10 @@ signals: void refreshHashtags(); protected: - void paintRegion(Painter &p, const QRegion ®ion, bool paintingOther); private: + void itemRemoved(HistoryItem *item); int dialogsOffset() const; int filteredOffset() const; @@ -288,8 +284,6 @@ public: void searchMessages(const QString &query, PeerData *inPeer = 0); void onSearchMore(); - void itemRemoved(HistoryItem *item); - void updateNotifySettings(PeerData *peer); void rpcClear() override { diff --git a/Telegram/SourceFiles/facades.cpp b/Telegram/SourceFiles/facades.cpp index de5c87220..f3c09b82b 100644 --- a/Telegram/SourceFiles/facades.cpp +++ b/Telegram/SourceFiles/facades.cpp @@ -661,6 +661,8 @@ struct Data { bool LocalPasscode = false; base::Observable LocalPasscodeChanged; + base::Observable ItemRemoved; + }; } // namespace internal @@ -774,4 +776,6 @@ DefineVar(Global, int, AutoLock); DefineVar(Global, bool, LocalPasscode); DefineRefVar(Global, base::Observable, LocalPasscodeChanged); +DefineRefVar(Global, base::Observable, ItemRemoved); + } // namespace Global diff --git a/Telegram/SourceFiles/facades.h b/Telegram/SourceFiles/facades.h index 89f6b2c36..40c378793 100644 --- a/Telegram/SourceFiles/facades.h +++ b/Telegram/SourceFiles/facades.h @@ -20,6 +20,8 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org */ #pragma once +#include "core/type_traits.h" + class LayerWidget; namespace base { template @@ -170,6 +172,10 @@ inline bool IsTopCorner(ScreenCorner corner) { } // namespace Notify +template <> +struct base::custom_is_fast_copy_type : public std_::true_type { +}; + #define DeclareReadOnlyVar(Type, Name) const Type &Name(); #define DeclareRefVar(Type, Name) DeclareReadOnlyVar(Type, Name) \ Type &Ref##Name(); @@ -346,6 +352,8 @@ DeclareVar(int, AutoLock); DeclareVar(bool, LocalPasscode); DeclareRefVar(base::Observable, LocalPasscodeChanged); +DeclareRefVar(base::Observable, ItemRemoved); + } // namespace Global namespace Adaptive { diff --git a/Telegram/SourceFiles/historywidget.cpp b/Telegram/SourceFiles/historywidget.cpp index 3ddf493b7..336ed9d9d 100644 --- a/Telegram/SourceFiles/historywidget.cpp +++ b/Telegram/SourceFiles/historywidget.cpp @@ -132,6 +132,9 @@ HistoryInner::HistoryInner(HistoryWidget *historyWidget, ScrollArea *scroll, His notifyIsBotChanged(); setMouseTracking(true); + subscribe(Global::RefItemRemoved(), [this](HistoryItem *item) { + itemRemoved(item); + }); } void HistoryInner::messagesReceived(PeerData *peer, const QVector &messages) { @@ -969,7 +972,11 @@ void HistoryInner::onDragExec() { } void HistoryInner::itemRemoved(HistoryItem *item) { - SelectedItems::iterator i = _selected.find(item); + if (_history != item->history() && _migrated != item->history()) { + return; + } + + auto i = _selected.find(item); if (i != _selected.cend()) { _selected.erase(i); _widget->updateTopBarSelection(); @@ -3130,7 +3137,10 @@ HistoryWidget::HistoryWidget(QWidget *parent) : TWidget(parent) connect(&_updateEditTimeLeftDisplay, SIGNAL(timeout()), this, SLOT(updateField())); - subscribe(Adaptive::Changed(), [this]() { update(); }); + subscribe(Adaptive::Changed(), [this] { update(); }); + subscribe(Global::RefItemRemoved(), [this](HistoryItem *item) { + itemRemoved(item); + }); } void HistoryWidget::start() { @@ -7044,7 +7054,6 @@ void HistoryWidget::resizeEvent(QResizeEvent *e) { } void HistoryWidget::itemRemoved(HistoryItem *item) { - if (_list) _list->itemRemoved(item); if (item == _replyEditMsg) { if (_editMsgId) { cancelEdit(); diff --git a/Telegram/SourceFiles/historywidget.h b/Telegram/SourceFiles/historywidget.h index 3e8c98f06..8afd763f2 100644 --- a/Telegram/SourceFiles/historywidget.h +++ b/Telegram/SourceFiles/historywidget.h @@ -46,11 +46,10 @@ class DragArea; class EmojiPan; class HistoryWidget; -class HistoryInner : public TWidget, public AbstractTooltipShower { +class HistoryInner : public TWidget, public AbstractTooltipShower, private base::Subscriber { Q_OBJECT public: - HistoryInner(HistoryWidget *historyWidget, ScrollArea *scroll, History *history); void messagesReceived(PeerData *peer, const QVector &messages); @@ -92,8 +91,6 @@ public: void fillSelectedItems(SelectedItemSet &sel, bool forDelete = true); void selectItem(HistoryItem *item); - void itemRemoved(HistoryItem *item); - void updateBotInfo(bool recount = true); bool wasSelectedText() const; @@ -126,7 +123,6 @@ protected: bool focusNextPrevChild(bool next) override; public slots: - void onUpdateSelected(); void onParentGeometryChanged(); @@ -146,11 +142,11 @@ public slots: void onDragExec(); private slots: - void onScrollDateCheck(); void onScrollDateHide(); private: + void itemRemoved(HistoryItem *item); void touchResetSpeed(); void touchUpdateSpeed(); @@ -633,7 +629,6 @@ public: void stopAnimActive(); void fillSelectedItems(SelectedItemSet &sel, bool forDelete = true); - void itemRemoved(HistoryItem *item); void itemEdited(HistoryItem *item); void updateScrollColors(); @@ -733,12 +728,10 @@ public: ~HistoryWidget(); signals: - void cancelled(); void historyShown(History *history, MsgId atMsgId); public slots: - void onCancel(); void onReplyToMessage(); void onEditMessage(); @@ -841,7 +834,6 @@ public slots: void preloadHistoryIfNeeded(); private slots: - void onHashtagOrBotCommandInsert(QString str, FieldAutocomplete::ChooseMethod method); void onMentionInsert(UserData *user); void onInlineBotCancel(); @@ -853,6 +845,7 @@ private slots: void updateField(); private: + void itemRemoved(HistoryItem *item); // Updates position of controls around the message field, // like send button, emoji button and others. diff --git a/Telegram/SourceFiles/mainwidget.cpp b/Telegram/SourceFiles/mainwidget.cpp index bdb328457..adfd05e65 100644 --- a/Telegram/SourceFiles/mainwidget.cpp +++ b/Telegram/SourceFiles/mainwidget.cpp @@ -73,6 +73,8 @@ MainWidget::MainWidget(MainWindow *window) : TWidget(window) , _dialogs(this) , _history(this) , _topBar(this) +, _playerPlaylist(this, Media::Player::Panel::Layout::OnlyPlaylist) +, _playerPanel(this, Media::Player::Panel::Layout::Full) , _mediaType(this) , _api(new ApiWrap(this)) { setGeometry(QRect(0, st::titleHeight, App::wnd()->width(), App::wnd()->height() - st::titleHeight)); @@ -120,6 +122,30 @@ MainWidget::MainWidget(MainWindow *window) : TWidget(window) }); connect(&_cacheBackgroundTimer, SIGNAL(timeout()), this, SLOT(onCacheBackground())); + if (Media::Player::exists()) { + _playerPanel->setPinCallback([this] { switchToFixedPlayer(); }); + subscribe(Media::Player::instance()->titleButtonOver(), [this](bool over) { + if (over) { + _playerPanel->showFromOther(); + } else { + _playerPanel->hideFromOther(); + } + }); + subscribe(Media::Player::instance()->playerWidgetOver(), [this](bool over) { + if (over) { + if (_playerPlaylist->isHidden()) { + auto position = mapFromGlobal(QCursor::pos()).x(); + auto bestPosition = _playerPlaylist->bestPositionFor(position); + if (rtl()) bestPosition = position + 2 * (position - bestPosition) - _playerPlaylist->width(); + updateMediaPlaylistPosition(bestPosition); + } + _playerPlaylist->showFromOther(); + } else { + _playerPlaylist->hideFromOther(); + } + }); + } + subscribe(Adaptive::Changed(), [this]() { updateAdaptiveLayout(); }); _dialogs->show(); @@ -175,6 +201,7 @@ bool MainWidget::onForward(const PeerId &peer, ForwardWhatMessages what) { _toForward.insert(item->id, item); } } + updateForwardingItemRemovedSubscription(); updateForwardingTexts(); Ui::showPeerHistory(peer, ShowAtUnreadMsgId); _history->onClearSelected(); @@ -277,11 +304,31 @@ void MainWidget::updateForwardingTexts() { _toForwardNameVersion = version; } +void MainWidget::updateForwardingItemRemovedSubscription() { + if (_toForward.isEmpty()) { + unsubscribe(_forwardingItemRemovedSubscription); + _forwardingItemRemovedSubscription = 0; + } else if (!_forwardingItemRemovedSubscription) { + _forwardingItemRemovedSubscription = subscribe(Global::RefItemRemoved(), [this](HistoryItem *item) { + auto i = _toForward.find(item->id); + if (i == _toForward.cend() || i.value() != item) { + i = _toForward.find(item->id - ServerMaxMsgId); + } + if (i != _toForward.cend() && i.value() == item) { + _toForward.erase(i); + updateForwardingItemRemovedSubscription(); + updateForwardingTexts(); + } + }); + } +} + void MainWidget::cancelForwarding() { if (_toForward.isEmpty()) return; _toForward.clear(); _history->cancelForwarding(); + updateForwardingItemRemovedSubscription(); } void MainWidget::finishForwarding(History *history, bool silent) { @@ -489,9 +536,8 @@ void MainWidget::ui_repaintHistoryItem(const HistoryItem *item) { if (item->history()->lastMsg == item) { item->history()->updateChatListEntry(); } - if (_playerPanel && !_playerPanel->isHidden()) { - _playerPanel->ui_repaintHistoryItem(item); - } + _playerPlaylist->ui_repaintHistoryItem(item); + _playerPanel->ui_repaintHistoryItem(item); if (_overview) _overview->ui_repaintHistoryItem(item); } @@ -1359,32 +1405,6 @@ void MainWidget::changingMsgId(HistoryItem *row, MsgId newId) { if (_overview) _overview->changingMsgId(row, newId); } -void MainWidget::itemRemoved(HistoryItem *item) { - _dialogs->itemRemoved(item); - if (_history->peer() == item->history()->peer || (_history->peer() && _history->peer() == item->history()->peer->migrateTo())) { - _history->itemRemoved(item); - } - if (_overview && (_overview->peer() == item->history()->peer || (_overview->peer() && _overview->peer() == item->history()->peer->migrateTo()))) { - _overview->itemRemoved(item); - } - if (_playerPanel) { - _playerPanel->itemRemoved(item); - } - if (!_toForward.isEmpty()) { - SelectedItemSet::iterator i = _toForward.find(item->id); - if (i != _toForward.cend() && i.value() == item) { - _toForward.erase(i); - updateForwardingTexts(); - } else { - i = _toForward.find(item->id - ServerMaxMsgId); - if (i != _toForward.cend() && i.value() == item) { - _toForward.erase(i); - updateForwardingTexts(); - } - } - } -} - void MainWidget::itemEdited(HistoryItem *item) { if (_history->peer() == item->history()->peer || (_history->peer() && _history->peer() == item->history()->peer->migrateTo())) { _history->itemEdited(item); @@ -1558,7 +1578,7 @@ void MainWidget::handleAudioUpdate(const AudioMsgId &audioId) { } if (playing == audioId && audioId.type() == AudioMsgId::Type::Song) { - if (!_playerPanel && !_player && Media::Player::exists()) { + if (!_playerUsingPanel && !_player && Media::Player::exists()) { createPlayer(); } } @@ -1574,19 +1594,20 @@ void MainWidget::handleAudioUpdate(const AudioMsgId &audioId) { } void MainWidget::switchToPanelPlayer() { + if (_playerUsingPanel) return; + _playerUsingPanel = true; + _player->slideUp(); _playerVolume.destroyDelayed(); - if (!_playerPanel) { - _playerPanel.create(this, Media::Player::Panel::Layout::Full); - _playerPanel->setPinCallback([this] { switchToFixedPlayer(); }); - updateMediaPlayerPosition(); - orderWidgets(); - Media::Player::instance()->createdNotifier().notify(Media::Player::PanelEvent(_playerPanel), true); - } + _playerPlaylist->hideIgnoringEnterEvents(); + + Media::Player::instance()->usePanelPlayer().notify(true, true); } void MainWidget::switchToFixedPlayer() { - _playerPanel.destroyDelayed(); + if (!_playerUsingPanel) return; + _playerUsingPanel = false; + if (!_player) { createPlayer(); } else { @@ -1597,6 +1618,9 @@ void MainWidget::switchToFixedPlayer() { updateMediaPlayerPosition(); } } + + Media::Player::instance()->usePanelPlayer().notify(false, true); + _playerPanel->hideIgnoringEnterEvents(); } void MainWidget::createPlayer() { @@ -1623,7 +1647,7 @@ void MainWidget::playerHeightUpdated() { _playerHeight = playerHeight; updateControlsGeometry(); } - if (_playerPanel && !_playerHeight && _player->isHidden()) { + if (_playerUsingPanel && !_playerHeight && _player->isHidden()) { _playerVolume.destroyDelayed(); _player.destroyDelayed(); } @@ -2319,6 +2343,15 @@ Window::SectionSlideParams MainWidget::prepareShowAnimation(bool willHaveTopBarS if (playerVolumeVisible) { _playerVolume->hide(); } + auto playerPanelVisible = !_playerPanel->isHidden(); + if (playerPanelVisible) { + _playerPanel->hide(); + } + auto playerPlaylistVisible = !_playerPlaylist->isHidden(); + if (playerPlaylistVisible) { + _playerPlaylist->hide(); + } + if (selectingPeer() && Adaptive::OneColumn()) { result.oldContentCache = myGrab(this, QRect(0, _playerHeight, _dialogsWidth, height() - _playerHeight)); } else if (_wideSection) { @@ -2341,9 +2374,16 @@ Window::SectionSlideParams MainWidget::prepareShowAnimation(bool willHaveTopBarS if (_overview) _overview->grabFinish(); _history->grabFinish(); } + if (playerVolumeVisible) { _playerVolume->show(); } + if (playerPanelVisible) { + _playerPanel->show(); + } + if (playerPlaylistVisible) { + _playerPlaylist->show(); + } if (_player) { _player->showShadow(); } @@ -2452,7 +2492,8 @@ void MainWidget::orderWidgets() { } _mediaType->raise(); _sideShadow->raise(); - if (_playerPanel) _playerPanel->raise(); + _playerPlaylist->raise(); + _playerPanel->raise(); if (_hider) _hider->raise(); } @@ -2473,6 +2514,15 @@ QPixmap MainWidget::grabForShowAnimation(const Window::SectionSlideParams ¶m if (playerVolumeVisible) { _playerVolume->hide(); } + auto playerPanelVisible = !_playerPanel->isHidden(); + if (playerPanelVisible) { + _playerPanel->hide(); + } + auto playerPlaylistVisible = !_playerPlaylist->isHidden(); + if (playerPlaylistVisible) { + _playerPlaylist->hide(); + } + if (Adaptive::OneColumn()) { result = myGrab(this, QRect(0, _playerHeight, _dialogsWidth, height() - _playerHeight)); } else { @@ -2483,6 +2533,12 @@ QPixmap MainWidget::grabForShowAnimation(const Window::SectionSlideParams ¶m if (playerVolumeVisible) { _playerVolume->show(); } + if (playerPanelVisible) { + _playerPanel->show(); + } + if (playerPlaylistVisible) { + _playerPlaylist->show(); + } if (_player) { _player->showShadow(); } @@ -2762,20 +2818,34 @@ void MainWidget::updateControlsGeometry() { } if (_overview) _overview->setGeometry(_history->geometry()); updateMediaPlayerPosition(); + updateMediaPlaylistPosition(_playerPlaylist->x()); _contentScrollAddToY = 0; } void MainWidget::updateMediaPlayerPosition() { - if (_playerPanel) { - _playerPanel->moveToRight(0, 0); - } - if (_playerVolume && _player) { + _playerPanel->moveToRight(0, 0); + if (_player && _playerVolume) { auto relativePosition = _player->entity()->getPositionForVolumeWidget(); auto playerMargins = _playerVolume->getMargin(); _playerVolume->moveToLeft(_player->x() + relativePosition.x() - playerMargins.left(), _player->y() + relativePosition.y() - playerMargins.top()); } } +void MainWidget::updateMediaPlaylistPosition(int x) { + if (_player) { + auto playlistLeft = x; + auto playlistWidth = _playerPlaylist->width(); + auto playlistTop = _player->y() + _player->height(); + auto rightEdge = width(); + if (playlistLeft + playlistWidth > rightEdge) { + playlistLeft = rightEdge - playlistWidth; + } else if (playlistLeft < 0) { + playlistLeft = 0; + } + _playerPlaylist->move(playlistLeft, playlistTop); + } +} + int MainWidget::contentScrollAddToY() const { return _contentScrollAddToY; } @@ -3529,7 +3599,8 @@ void MainWidget::onSelfParticipantUpdated(ChannelData *channel) { bool MainWidget::contentOverlapped(const QRect &globalRect) { return (_history->contentOverlapped(globalRect) || - (_playerPanel && _playerPanel->overlaps(globalRect)) || + _playerPanel->overlaps(globalRect) || + _playerPlaylist->overlaps(globalRect) || (_playerVolume && _playerVolume->overlaps(globalRect)) || _mediaType->overlaps(globalRect)); } diff --git a/Telegram/SourceFiles/mainwidget.h b/Telegram/SourceFiles/mainwidget.h index 73d1f6dea..cdf4d3409 100644 --- a/Telegram/SourceFiles/mainwidget.h +++ b/Telegram/SourceFiles/mainwidget.h @@ -307,7 +307,6 @@ public: void preloadOverviews(PeerData *peer); void mediaOverviewUpdated(PeerData *peer, MediaOverviewType type); void changingMsgId(HistoryItem *row, MsgId newId); - void itemRemoved(HistoryItem *item); void itemEdited(HistoryItem *item); void loadMediaBack(PeerData *peer, MediaOverviewType type, bool many = false); @@ -340,7 +339,6 @@ public: bool hasForwardingItems(); void fillForwardingInfo(Text *&from, Text *&text, bool &serviceColor, ImagePtr &preview); - void updateForwardingTexts(); void cancelForwarding(); void finishForwarding(History *hist, bool silent); // send them @@ -484,8 +482,12 @@ private: void updateAdaptiveLayout(); void handleAudioUpdate(const AudioMsgId &audioId); void updateMediaPlayerPosition(); + void updateMediaPlaylistPosition(int x); void updateControlsGeometry(); + void updateForwardingTexts(); + void updateForwardingItemRemovedSubscription(); + void createPlayer(); void switchToPanelPlayer(); void switchToFixedPlayer(); @@ -520,6 +522,7 @@ private: SelectedItemSet _toForward; Text _toForwardFrom, _toForwardText; int32 _toForwardNameVersion = 0; + int _forwardingItemRemovedSubscription = 0; OrderedSet _webPagesUpdated; OrderedSet _gamesUpdated; @@ -589,9 +592,13 @@ private: ChildWidget _wideSection = { nullptr }; ChildWidget _overview = { nullptr }; ChildWidget _topBar; + ChildWidget _player = { nullptr }; ChildWidget _playerVolume = { nullptr }; - ChildWidget _playerPanel = { nullptr }; + ChildWidget _playerPlaylist; + ChildWidget _playerPanel; + bool _playerUsingPanel = false; + ConfirmBox *_forwardConfirm = nullptr; // for single column layout ChildWidget _hider = { nullptr }; std_::vector_of_moveable> _stack; diff --git a/Telegram/SourceFiles/mainwindow.cpp b/Telegram/SourceFiles/mainwindow.cpp index 8b4001dad..cbba2a63b 100644 --- a/Telegram/SourceFiles/mainwindow.cpp +++ b/Telegram/SourceFiles/mainwindow.cpp @@ -90,7 +90,7 @@ MainWindow::MainWindow() { iconbig32 = iconbig256.scaledToWidth(32, Qt::SmoothTransformation); iconbig64 = iconbig256.scaledToWidth(64, Qt::SmoothTransformation); - subscribe(Global::RefNotifySettingsChanged(), [this](const Notify::ChangeType &type) { + subscribe(Global::RefNotifySettingsChanged(), [this](Notify::ChangeType type) { if (type == Notify::ChangeType::DesktopEnabled) { updateTrayMenu(); notifyClear(); diff --git a/Telegram/SourceFiles/media/player/media_player.style b/Telegram/SourceFiles/media/player/media_player.style index a724f65ce..2e3049018 100644 --- a/Telegram/SourceFiles/media/player/media_player.style +++ b/Telegram/SourceFiles/media/player/media_player.style @@ -239,13 +239,20 @@ mediaPlayerScroll: flatScroll(solidScroll) { } mediaPlayerListHeightMax: 280px; mediaPlayerListMarginBottom: 10px; -mediaPlayerScrollShadow: icon {{ "player_playlist_shadow", #000000 }}; +mediaPlayerScrollShadow: icon {{ "playlist_shadow", #000000 }}; mediaPlayerListMarginTop: 8px; +mediaPlayerListIconFg: #ffffff; mediaPlayerFileLayout: OverviewFileLayout(overviewFileLayout) { maxWidth: 344px; songPadding: margins(17px, 7px, 10px, 6px); songThumbSize: 36px; songNameTop: 7px; songStatusTop: 25px; + songIconBg: mediaPlayerActiveFg; + songOverBg: mediaPlayerActiveFg; + songPause: icon {{ "playlist_pause", mediaPlayerListIconFg }}; + songPlay: icon {{ "playlist_play", mediaPlayerListIconFg }}; + songCancel: icon {{ "playlist_cancel", mediaPlayerListIconFg }}; + songDownload: icon {{ "playlist_download", mediaPlayerListIconFg }}; } diff --git a/Telegram/SourceFiles/media/player/media_player_cover.cpp b/Telegram/SourceFiles/media/player/media_player_cover.cpp index b564fddad..68a938882 100644 --- a/Telegram/SourceFiles/media/player/media_player_cover.cpp +++ b/Telegram/SourceFiles/media/player/media_player_cover.cpp @@ -80,6 +80,7 @@ CoverWidget::CoverWidget(QWidget *parent) : TWidget(parent) , _pinPlayer(this, st::mediaPlayerPanelPinButton) , _repeatTrack(this, st::mediaPlayerRepeatButton) { setAttribute(Qt::WA_OpaquePaintEvent); + resize(width(), st::mediaPlayerCoverHeight); _playback->setChangeProgressCallback([this](float64 value) { handleSeekProgress(value); @@ -315,12 +316,14 @@ void CoverWidget::handlePlaylistUpdate() { void CoverWidget::createPrevNextButtons() { if (!_previousTrack) { _previousTrack.create(this, st::mediaPlayerPanelPreviousButton); - _nextTrack.create(this, st::mediaPlayerPanelNextButton); + _previousTrack->show(); _previousTrack->setClickedCallback([this]() { if (exists()) { instance()->previous(); } }); + _nextTrack.create(this, st::mediaPlayerPanelNextButton); + _nextTrack->show(); _nextTrack->setClickedCallback([this]() { if (exists()) { instance()->next(); diff --git a/Telegram/SourceFiles/media/player/media_player_instance.h b/Telegram/SourceFiles/media/player/media_player_instance.h index ccf892a4c..9891e34fc 100644 --- a/Telegram/SourceFiles/media/player/media_player_instance.h +++ b/Telegram/SourceFiles/media/player/media_player_instance.h @@ -40,12 +40,6 @@ bool exists(); class Instance; Instance *instance(); -class Panel; -struct PanelEvent { - explicit PanelEvent(Panel *panel) : panel(panel) { - } - Panel *panel; -}; struct UpdatedEvent { UpdatedEvent(const AudioMsgId *audioId, const AudioPlaybackState *playbackState) : audioId(audioId), playbackState(playbackState) { } @@ -87,11 +81,14 @@ public: return _playlist; } - base::Observable &createdNotifier() { - return _createdNotifier; + base::Observable &usePanelPlayer() { + return _usePanelPlayer; } - base::Observable &destroyedNotifier() { - return _destroyedNotifier; + base::Observable &titleButtonOver() { + return _titleButtonOver; + } + base::Observable &playerWidgetOver() { + return _playerWidgetOver; } base::Observable &updatedNotifier() { return _updatedNotifier; @@ -133,8 +130,9 @@ private: QList _playlist; bool _isPlaying = false; - base::Observable _createdNotifier; - base::Observable _destroyedNotifier; + base::Observable _usePanelPlayer; + base::Observable _titleButtonOver; + base::Observable _playerWidgetOver; base::Observable _updatedNotifier; base::Observable _playlistChangedNotifier; base::Observable _songChangedNotifier; diff --git a/Telegram/SourceFiles/media/player/media_player_list.cpp b/Telegram/SourceFiles/media/player/media_player_list.cpp index c04f45975..522ce7e41 100644 --- a/Telegram/SourceFiles/media/player/media_player_list.cpp +++ b/Telegram/SourceFiles/media/player/media_player_list.cpp @@ -34,6 +34,9 @@ ListWidget::ListWidget() { if (exists()) { subscribe(instance()->playlistChangedNotifier(), [this] { playlistUpdated(); }); } + subscribe(Global::RefItemRemoved(), [this](HistoryItem *item) { + itemRemoved(item); + }); } ListWidget::~ListWidget() { @@ -143,10 +146,32 @@ void ListWidget::itemRemoved(HistoryItem *item) { if (layoutIt != _layouts.cend()) { auto layout = layoutIt.value(); _layouts.erase(layoutIt); + + for (int i = 0, count = _list.size(); i != count; ++i) { + if (_list[i] == layout) { + _list.removeAt(i); + break; + } + } delete layout; } } +QRect ListWidget::getCurrentTrackGeometry() const { + if (exists()) { + auto top = marginTop(); + auto current = instance()->current(); + for_const (auto layout, _list) { + auto layoutHeight = layout->height(); + if (layout->getItem()->fullId() == current.contextId()) { + return QRect(0, top, width(), layoutHeight); + } + top += layoutHeight; + } + } + return QRect(0, height(), width(), 0); +} + int ListWidget::resizeGetHeight(int newWidth) { auto result = 0; for_const (auto layout, _list) { diff --git a/Telegram/SourceFiles/media/player/media_player_list.h b/Telegram/SourceFiles/media/player/media_player_list.h index ed8e5dd95..bead9a398 100644 --- a/Telegram/SourceFiles/media/player/media_player_list.h +++ b/Telegram/SourceFiles/media/player/media_player_list.h @@ -34,7 +34,8 @@ public: ListWidget(); void ui_repaintHistoryItem(const HistoryItem *item); - void itemRemoved(HistoryItem *item); + + QRect getCurrentTrackGeometry() const; ~ListWidget(); @@ -47,6 +48,7 @@ protected: int resizeGetHeight(int newWidth) override; private: + void itemRemoved(HistoryItem *item); int marginTop() const; void repaintItem(const HistoryItem *item); void playlistUpdated(); diff --git a/Telegram/SourceFiles/media/player/media_player_panel.cpp b/Telegram/SourceFiles/media/player/media_player_panel.cpp index 24bd7e910..95ab3a971 100644 --- a/Telegram/SourceFiles/media/player/media_player_panel.cpp +++ b/Telegram/SourceFiles/media/player/media_player_panel.cpp @@ -24,6 +24,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org #include "media/player/media_player_cover.h" #include "media/player/media_player_list.h" #include "media/player/media_player_instance.h" +#include "styles/style_overview.h" #include "styles/style_media_player.h" #include "ui/widgets/shadow.h" #include "mainwindow.h" @@ -32,36 +33,25 @@ namespace Media { namespace Player { Panel::Panel(QWidget *parent, Layout layout) : TWidget(parent) +, _layout(layout) , _shadow(st::defaultInnerDropdown.shadow) -, _scroll(this, st::mediaPlayerScroll) -, _scrollShadow(this, st::mediaPlayerScrollShadow) { - if (layout == Layout::Full) { - _cover.create(this); - } +, _scroll(this, st::mediaPlayerScroll) { _hideTimer.setSingleShot(true); connect(&_hideTimer, SIGNAL(timeout()), this, SLOT(onHideStart())); - auto list = std_::make_unique(); - connect(list.get(), SIGNAL(heightUpdated()), this, SLOT(onListHeightUpdated())); - _scroll->setOwnedWidget(list.release()); - _showTimer.setSingleShot(true); connect(&_showTimer, SIGNAL(timeout()), this, SLOT(onShowStart())); - if (cPlatform() == dbipMac || cPlatform() == dbipMacOld) { - connect(App::wnd()->windowHandle(), SIGNAL(activeChanged()), this, SLOT(onWindowActiveChanged())); - } - hide(); - onListHeightUpdated(); + updateSize(); } bool Panel::overlaps(const QRect &globalRect) { if (isHidden() || _a_appearance.animating()) return false; - auto marginLeft = rtl() ? 0 : contentLeft(); - auto marginRight = rtl() ? contentLeft() : 0; - return rect().marginsRemoved(QMargins(marginLeft, 0, marginRight, st::mediaPlayerPanelMarginBottom)).contains(QRect(mapFromGlobal(globalRect.topLeft()), globalRect.size())); + auto marginLeft = rtl() ? contentRight() : contentLeft(); + auto marginRight = rtl() ? contentLeft() : contentRight(); + return rect().marginsRemoved(QMargins(marginLeft, contentTop(), marginRight, contentBottom())).contains(QRect(mapFromGlobal(globalRect.topLeft()), globalRect.size())); } void Panel::onWindowActiveChanged() { @@ -71,16 +61,28 @@ void Panel::onWindowActiveChanged() { } void Panel::resizeEvent(QResizeEvent *e) { - auto width = contentWidth(); - _cover->resize(width, st::mediaPlayerCoverHeight); - _cover->moveToRight(0, 0); + updateControlsGeometry(); +} - auto scrollTop = _cover->height(); - auto scrollHeight = qMax(contentHeight() - scrollTop - st::mediaPlayerListMarginBottom, 0); +void Panel::onListHeightUpdated() { + updateSize(); +} + +void Panel::updateControlsGeometry() { + auto scrollTop = contentTop(); + auto width = contentWidth(); + if (_cover) { + _cover->resizeToWidth(width); + _cover->moveToRight(contentRight(), scrollTop); + scrollTop += _cover->height(); + if (_scrollShadow) { + _scrollShadow->resizeToWidth(width); + _scrollShadow->moveToRight(contentRight(), scrollTop); + } + } + auto scrollHeight = qMax(height() - scrollTop - contentBottom() - scrollMarginBottom(), 0); if (scrollHeight > 0) { - _scroll->setGeometryToRight(0, scrollTop, width, scrollHeight); - _scrollShadow->resizeToWidth(width); - _scrollShadow->moveToRight(0, scrollTop); + _scroll->setGeometryToRight(contentRight(), scrollTop, width, scrollHeight); } if (auto widget = static_cast(_scroll->widget())) { widget->resizeToWidth(width); @@ -88,19 +90,28 @@ void Panel::resizeEvent(QResizeEvent *e) { } } -void Panel::onListHeightUpdated() { - updateSize(); -} - void Panel::ui_repaintHistoryItem(const HistoryItem *item) { if (auto list = static_cast(_scroll->widget())) { list->ui_repaintHistoryItem(item); } } -void Panel::itemRemoved(HistoryItem *item) { +int Panel::bestPositionFor(int left) const { + left -= contentLeft(); + left -= st::mediaPlayerFileLayout.songPadding.left(); + left -= st::mediaPlayerFileLayout.songThumbSize / 2; + return left; +} + +void Panel::scrollPlaylistToCurrentTrack() { if (auto list = static_cast(_scroll->widget())) { - list->itemRemoved(item); + auto rect = list->getCurrentTrackGeometry(); + auto top = _scroll->scrollTop(), bottom = top + _scroll->height(); + _scroll->scrollToY(rect.y()); + //if (top > rect.y()) { + //} else if (bottom < rect.y() + rect.height()) { + // _scroll->scrollToY(rect.y() + rect.height() - _scroll->height()); + //} } } @@ -113,17 +124,23 @@ void Panel::onScroll() { } void Panel::updateSize() { + auto width = contentLeft() + st::mediaPlayerPanelWidth + contentRight(); + auto height = contentTop(); + if (_cover) { + height += _cover->height(); + } auto listHeight = 0; if (auto widget = static_cast(_scroll->widget())) { listHeight = widget->height(); } auto scrollVisible = (listHeight > 0); auto scrollHeight = scrollVisible ? (qMin(listHeight, st::mediaPlayerListHeightMax) + st::mediaPlayerListMarginBottom) : 0; - auto width = contentLeft() + st::mediaPlayerPanelWidth; - auto height = st::mediaPlayerCoverHeight + scrollHeight + st::mediaPlayerPanelMarginBottom; + height += scrollHeight + contentBottom(); resize(width, height); _scroll->setVisible(scrollVisible); - _scrollShadow->setVisible(scrollVisible); + if (_scrollShadow) { + _scrollShadow->setVisible(scrollVisible); + } } void Panel::paintEvent(QPaintEvent *e) { @@ -146,13 +163,19 @@ void Panel::paintEvent(QPaintEvent *e) { } // draw shadow - auto shadowedRect = myrtlrect(contentLeft(), 0, contentWidth(), height() - st::mediaPlayerPanelMarginBottom); - auto shadowedSides = (rtl() ? Ui::RectShadow::Side::Right : Ui::RectShadow::Side::Left) | Ui::RectShadow::Side::Bottom; + using Side = Ui::RectShadow::Side; + auto shadowedRect = myrtlrect(contentLeft(), contentTop(), contentWidth(), contentHeight()); + auto shadowedSides = (rtl() ? Side::Right : Side::Left) | Side::Bottom; + if (_layout != Layout::Full) { + shadowedSides |= (rtl() ? Side::Left : Side::Right) | Side::Top; + } _shadow.paint(p, shadowedRect, st::defaultInnerDropdown.shadowShift, shadowedSides); p.fillRect(shadowedRect, st::windowBg); } void Panel::enterEvent(QEvent *e) { + if (_ignoringEnterEvents) return; + _hideTimer.stop(); if (_a_appearance.animating(getms())) { onShowStart(); @@ -172,7 +195,7 @@ void Panel::leaveEvent(QEvent *e) { return TWidget::leaveEvent(e); } -void Panel::otherEnter() { +void Panel::showFromOther() { _hideTimer.stop(); if (_a_appearance.animating(getms())) { onShowStart(); @@ -181,7 +204,7 @@ void Panel::otherEnter() { } } -void Panel::otherLeave() { +void Panel::hideFromOther() { _showTimer.stop(); if (_a_appearance.animating(getms())) { onHideStart(); @@ -190,20 +213,56 @@ void Panel::otherLeave() { } } -void Panel::setPinCallback(PinCallback &&callback) { - if (_cover) { - _cover->setPinCallback(std_::move(callback)); +void Panel::ensureCreated() { + if (_scroll->widget()) return; + + if (_layout == Layout::Full) { + _cover.create(this); + setPinCallback(std_::move(_pinCallback)); + + _scrollShadow.create(this, st::mediaPlayerScrollShadow); + } + auto list = std_::make_unique(); + connect(list.get(), SIGNAL(heightUpdated()), this, SLOT(onListHeightUpdated())); + _scroll->setOwnedWidget(list.release()); + + if (cPlatform() == dbipMac || cPlatform() == dbipMacOld) { + if (auto window = App::wnd()) { + connect(window->windowHandle(), SIGNAL(activeChanged()), this, SLOT(onWindowActiveChanged())); + } + } + + updateSize(); + updateControlsGeometry(); + _ignoringEnterEvents = false; +} + +void Panel::performDestroy() { + if (!_scroll->widget()) return; + + _cover.destroy(); + auto list = _scroll->takeWidget(); + list->hide(); + list->deleteLater(); + + if (cPlatform() == dbipMac || cPlatform() == dbipMacOld) { + if (auto window = App::wnd()) { + disconnect(window->windowHandle(), SIGNAL(activeChanged()), this, SLOT(onWindowActiveChanged())); + } } } -Panel::~Panel() { - if (exists()) { - instance()->destroyedNotifier().notify(Media::Player::PanelEvent(this), true); +void Panel::setPinCallback(PinCallback &&callback) { + _pinCallback = std_::move(callback); + if (_cover) { + _cover->setPinCallback(PinCallback(_pinCallback)); } } void Panel::onShowStart() { + ensureCreated(); if (isHidden()) { + scrollPlaylistToCurrentTrack(); show(); } else if (!_hiding) { return; @@ -212,8 +271,17 @@ void Panel::onShowStart() { startAnimation(); } +void Panel::hideIgnoringEnterEvents() { + _ignoringEnterEvents = true; + if (isHidden()) { + hidingFinished(); + } else { + onHideStart(); + } +} + void Panel::onHideStart() { - if (_hiding) return; + if (_hiding || isHidden()) return; _hiding = true; startAnimation(); @@ -242,23 +310,27 @@ void Panel::appearanceCallback() { void Panel::hidingFinished() { hide(); _cache = QPixmap(); + performDestroy(); } int Panel::contentLeft() const { return st::mediaPlayerPanelMarginLeft; } -int Panel::contentHeight() const { - return height() - st::mediaPlayerPanelMarginBottom; +int Panel::contentTop() const { + return (_layout == Layout::Full) ? 0 : st::mediaPlayerPanelMarginLeft; } -bool Panel::eventFilter(QObject *obj, QEvent *e) { - if (e->type() == QEvent::Enter) { - otherEnter(); - } else if (e->type() == QEvent::Leave) { - otherLeave(); - } - return false; +int Panel::contentRight() const { + return (_layout == Layout::Full) ? 0 : st::mediaPlayerPanelMarginLeft; +} + +int Panel::contentBottom() const { + return st::mediaPlayerPanelMarginBottom; +} + +int Panel::scrollMarginBottom() const { + return st::mediaPlayerPanelMarginBottom; } } // namespace Player diff --git a/Telegram/SourceFiles/media/player/media_player_panel.h b/Telegram/SourceFiles/media/player/media_player_panel.h index 2f863d5f9..b35d8d7a8 100644 --- a/Telegram/SourceFiles/media/player/media_player_panel.h +++ b/Telegram/SourceFiles/media/player/media_player_panel.h @@ -34,7 +34,7 @@ namespace Player { class CoverWidget; class ListWidget; -class Panel : public TWidget, private base::Subscriber { +class Panel : public TWidget { Q_OBJECT public: @@ -44,19 +44,19 @@ public: }; Panel(QWidget *parent, Layout layout); - void setLayout(Layout layout); bool overlaps(const QRect &globalRect); - void otherEnter(); - void otherLeave(); + void hideIgnoringEnterEvents(); - using PinCallback = base::lambda_unique; + void showFromOther(); + void hideFromOther(); + + using PinCallback = base::lambda_wrap; void setPinCallback(PinCallback &&callback); void ui_repaintHistoryItem(const HistoryItem *item); - void itemRemoved(HistoryItem *item); - ~Panel(); + int bestPositionFor(int left) const; protected: void resizeEvent(QResizeEvent *e) override; @@ -64,40 +64,53 @@ protected: void enterEvent(QEvent *e) override; void leaveEvent(QEvent *e) override; - bool eventFilter(QObject *obj, QEvent *e) override; - private slots: void onShowStart(); void onHideStart(); + void onScroll(); - void onListHeightUpdated(); - void onWindowActiveChanged(); private: + void ensureCreated(); + void performDestroy(); + + void updateControlsGeometry(); + void updateSize(); void appearanceCallback(); void hidingFinished(); int contentLeft() const; + int contentTop() const; + int contentRight() const; + int contentBottom() const; + int scrollMarginBottom() const; int contentWidth() const { - return width() - contentLeft(); + return width() - contentLeft() - contentRight(); + } + int contentHeight() const { + return height() - contentTop() - contentBottom();; } - int contentHeight() const; void startAnimation(); + void scrollPlaylistToCurrentTrack(); + Layout _layout; bool _hiding = false; QPixmap _cache; FloatAnimation _a_appearance; + bool _ignoringEnterEvents = false; + QTimer _hideTimer, _showTimer; Ui::RectShadow _shadow; + PinCallback _pinCallback; ChildWidget _cover = { nullptr }; ChildWidget _scroll; - ChildWidget _scrollShadow; + ChildWidget _scrollShadow = { nullptr }; }; diff --git a/Telegram/SourceFiles/media/player/media_player_title_button.cpp b/Telegram/SourceFiles/media/player/media_player_title_button.cpp index 12b500adc..2903a10af 100644 --- a/Telegram/SourceFiles/media/player/media_player_title_button.cpp +++ b/Telegram/SourceFiles/media/player/media_player_title_button.cpp @@ -102,6 +102,20 @@ void TitleButton::paintIcon(Painter &p) { _layout->paint(p, icon); } +void TitleButton::enterEvent(QEvent *e) { + if (exists()) { + instance()->titleButtonOver().notify(true, true); + } + return Button::enterEvent(e); +} + +void TitleButton::leaveEvent(QEvent *e) { + if (exists()) { + instance()->titleButtonOver().notify(false, true); + } + return Button::leaveEvent(e); +} + TitleButton::~TitleButton() = default; } // namespace Player diff --git a/Telegram/SourceFiles/media/player/media_player_title_button.h b/Telegram/SourceFiles/media/player/media_player_title_button.h index a240e95d8..b9b0f4e47 100644 --- a/Telegram/SourceFiles/media/player/media_player_title_button.h +++ b/Telegram/SourceFiles/media/player/media_player_title_button.h @@ -37,6 +37,8 @@ public: protected: void paintEvent(QPaintEvent *e) override; + void enterEvent(QEvent *e) override; + void leaveEvent(QEvent *e) override; void onStateChanged(int oldState, ButtonStateChangeSource source) override; diff --git a/Telegram/SourceFiles/media/player/media_player_widget.cpp b/Telegram/SourceFiles/media/player/media_player_widget.cpp index 70a6b7619..32f309d4b 100644 --- a/Telegram/SourceFiles/media/player/media_player_widget.cpp +++ b/Telegram/SourceFiles/media/player/media_player_widget.cpp @@ -81,8 +81,12 @@ Widget::Widget(QWidget *parent) : TWidget(parent) , _shadow(this, st::shadowColor) , _playback(new Ui::FilledSlider(this, st::mediaPlayerPlayback)) { setAttribute(Qt::WA_OpaquePaintEvent); + setMouseTracking(true); resize(st::wndMinWidth, st::mediaPlayerHeight + st::lineWidth); + _nameLabel->setAttribute(Qt::WA_TransparentForMouseEvents); + _timeLabel->setAttribute(Qt::WA_TransparentForMouseEvents); + _playback->setChangeProgressCallback([this](float64 value) { handleSeekProgress(value); }); @@ -226,6 +230,28 @@ void Widget::paintEvent(QPaintEvent *e) { } } +void Widget::leaveEvent(QEvent *e) { + updateOverLabelsState(false); +} + +void Widget::mouseMoveEvent(QMouseEvent *e) { + updateOverLabelsState(e->pos()); +} + +void Widget::updateOverLabelsState(QPoint pos) { + auto left = getLabelsLeft(); + auto right = getLabelsRight(); + auto labels = myrtlrect(left, 0, width() - right - left, height() - st::mediaPlayerPlayback.fullWidth); + auto over = labels.contains(pos); + updateOverLabelsState(over); +} + +void Widget::updateOverLabelsState(bool over) { + if (exists()) { + instance()->playerWidgetOver().notify(over, true); + } +} + void Widget::updatePlayPrevNextPositions() { auto left = st::mediaPlayerPlayLeft; auto top = st::mediaPlayerPlayTop; @@ -238,15 +264,24 @@ void Widget::updatePlayPrevNextPositions() { } } -void Widget::updateLabelsGeometry() { - auto left = st::mediaPlayerPlayLeft + _playPause->width(); +int Widget::getLabelsLeft() const { + auto result = st::mediaPlayerPlayLeft + _playPause->width(); if (_previousTrack) { - left += _previousTrack->width() + st::mediaPlayerPlaySkip + _nextTrack->width() + st::mediaPlayerPlaySkip; + result += _previousTrack->width() + st::mediaPlayerPlaySkip + _nextTrack->width() + st::mediaPlayerPlaySkip; } - left += st::mediaPlayerPadding; + result += st::mediaPlayerPadding; + return result; +} - auto right = st::mediaPlayerCloseRight + _close->width() + _repeatTrack->width() + _volumeToggle->width(); - right += st::mediaPlayerPadding; +int Widget::getLabelsRight() const { + auto result = st::mediaPlayerCloseRight + _close->width() + _repeatTrack->width() + _volumeToggle->width(); + result += st::mediaPlayerPadding; + return result; +} + +void Widget::updateLabelsGeometry() { + auto left = getLabelsLeft(); + auto right = getLabelsRight(); auto widthForName = width() - left - right; widthForName -= _timeLabel->width() + 2 * st::normalFont->spacew; @@ -367,12 +402,14 @@ void Widget::handlePlaylistUpdate() { void Widget::createPrevNextButtons() { if (!_previousTrack) { _previousTrack.create(this, st::mediaPlayerPreviousButton); - _nextTrack.create(this, st::mediaPlayerNextButton); + _previousTrack->show(); _previousTrack->setClickedCallback([this]() { if (exists()) { instance()->previous(); } }); + _nextTrack.create(this, st::mediaPlayerNextButton); + _nextTrack->show(); _nextTrack->setClickedCallback([this]() { if (exists()) { instance()->next(); diff --git a/Telegram/SourceFiles/media/player/media_player_widget.h b/Telegram/SourceFiles/media/player/media_player_widget.h index fb3380f34..edc58b16e 100644 --- a/Telegram/SourceFiles/media/player/media_player_widget.h +++ b/Telegram/SourceFiles/media/player/media_player_widget.h @@ -59,10 +59,18 @@ protected: void resizeEvent(QResizeEvent *e) override; void paintEvent(QPaintEvent *e) override; + void leaveEvent(QEvent *e) override; + void mouseMoveEvent(QMouseEvent *e) override; + private: void handleSeekProgress(float64 progress); void handleSeekFinished(float64 progress); + int getLabelsLeft() const; + int getLabelsRight() const; + void updateOverLabelsState(QPoint pos); + void updateOverLabelsState(bool over); + void updatePlayPrevNextPositions(); void updateLabelsGeometry(); void updateRepeatTrackIcon(); @@ -81,6 +89,7 @@ private: int64 _seekPositionMs = -1; int64 _lastDurationMs = 0; QString _time; + bool _mouseOverLabels = false; class PlayButton; ChildWidget _nameLabel; diff --git a/Telegram/SourceFiles/media/view/media_clip_playback.cpp b/Telegram/SourceFiles/media/view/media_clip_playback.cpp index cec0da687..0357fea84 100644 --- a/Telegram/SourceFiles/media/view/media_clip_playback.cpp +++ b/Telegram/SourceFiles/media/view/media_clip_playback.cpp @@ -33,7 +33,9 @@ Playback::Playback(Ui::ContinuousSlider *slider) : _slider(slider) { void Playback::updateState(const AudioPlaybackState &playbackState) { qint64 position = 0, duration = playbackState.duration; - setDisabled(false); + auto wasDisabled = _slider->isDisabled(); + if (wasDisabled) setDisabled(false); + _playing = !(playbackState.state & AudioPlayerStoppedMask); if (_playing || playbackState.state == AudioPlayerStopped) { position = playbackState.position; @@ -49,7 +51,7 @@ void Playback::updateState(const AudioPlaybackState &playbackState) { } else if (duration) { progress = duration ? snap(float64(position) / duration, 0., 1.) : 0.; } - if (duration != _duration || position != _position) { + if (duration != _duration || position != _position || wasDisabled) { auto animated = (duration && _duration && progress > _slider->value()); _slider->setValue(progress, animated); _position = position; diff --git a/Telegram/SourceFiles/overview/overview.style b/Telegram/SourceFiles/overview/overview.style index 50413c17c..c010d0191 100644 --- a/Telegram/SourceFiles/overview/overview.style +++ b/Telegram/SourceFiles/overview/overview.style @@ -19,6 +19,7 @@ Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org */ using "basic.style"; +using "history/history.style"; OverviewFileLayout { maxWidth: pixels; @@ -26,6 +27,13 @@ OverviewFileLayout { songThumbSize: pixels; songNameTop: pixels; songStatusTop: pixels; + songIconBg: color; + songOverBg: color; + songPause: icon; + songPlay: icon; + songCancel: icon; + songDownload: icon; + filePadding: margins; fileThumbSize: pixels; fileNameTop: pixels; @@ -61,6 +69,13 @@ overviewFileLayout: OverviewFileLayout { songThumbSize: msgFileSize; songNameTop: msgFileNameTop; songStatusTop: msgFileStatusTop; + songIconBg: msgFileInBg; + songOverBg: msgFileInBgOver; + songPause: historyFileInPause; + songPlay: historyFileInPlay; + songCancel: historyFileInCancel; + songDownload: historyFileInDownload; + filePadding: margins(0px, 3px, 16px, 3px); fileThumbSize: 70px; fileNameTop: 7px; diff --git a/Telegram/SourceFiles/overview/overview_layout.cpp b/Telegram/SourceFiles/overview/overview_layout.cpp index b80b53824..e8d8f4ce7 100644 --- a/Telegram/SourceFiles/overview/overview_layout.cpp +++ b/Telegram/SourceFiles/overview/overview_layout.cpp @@ -667,10 +667,10 @@ void Document::paint(Painter &p, const QRect &clip, TextSelection selection, con } else if (_a_iconOver.animating()) { _a_iconOver.step(context->ms); float64 over = a_iconOver.current(); - p.setBrush(style::interpolate(st::msgFileInBg, st::msgFileInBgOver, over)); + p.setBrush(style::interpolate(_st.songIconBg, _st.songOverBg, over)); } else { bool over = ClickHandler::showAsActive(loaded ? _openl : (_data->loading() ? _cancell : _openl)); - p.setBrush(over ? st::msgFileInBgOver : st::msgFileInBg); + p.setBrush(over ? _st.songOverBg : _st.songIconBg); } p.setRenderHint(QPainter::HighQualityAntialiasing); @@ -685,13 +685,13 @@ void Document::paint(Painter &p, const QRect &clip, TextSelection selection, con auto icon = ([showPause, loaded, this, selected] { if (showPause) { - return &(selected ? st::historyFileInPauseSelected : st::historyFileInPause); + return &(selected ? st::historyFileInPauseSelected : _st.songPause); } else if (loaded) { - return &(selected ? st::historyFileInPlaySelected : st::historyFileInPlay); + return &(selected ? st::historyFileInPlaySelected : _st.songPlay); } else if (_data->loading()) { - return &(selected ? st::historyFileInCancelSelected : st::historyFileInCancel); + return &(selected ? st::historyFileInCancelSelected : _st.songCancel); } - return &(selected ? st::historyFileInDownloadSelected : st::historyFileInDownload); + return &(selected ? st::historyFileInDownloadSelected : _st.songDownload); })(); icon->paintInCenter(p, inner); } diff --git a/Telegram/SourceFiles/overviewwidget.cpp b/Telegram/SourceFiles/overviewwidget.cpp index 50883ebe9..2271e58b4 100644 --- a/Telegram/SourceFiles/overviewwidget.cpp +++ b/Telegram/SourceFiles/overviewwidget.cpp @@ -38,59 +38,24 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org // flick scroll taken from http://qt-project.org/doc/qt-4.8/demos-embedded-anomaly-src-flickcharm-cpp.html -OverviewInner::OverviewInner(OverviewWidget *overview, ScrollArea *scroll, PeerData *peer, MediaOverviewType type) : QWidget(0) +OverviewInner::OverviewInner(OverviewWidget *overview, ScrollArea *scroll, PeerData *peer, MediaOverviewType type) : TWidget(nullptr) , _overview(overview) , _scroll(scroll) -, _resizeIndex(-1) -, _resizeSkip(0) , _peer(peer->migrateTo() ? peer->migrateTo() : peer) , _type(type) , _reversed(_type != OverviewFiles && _type != OverviewLinks) , _migrated(_peer->migrateFrom() ? App::history(_peer->migrateFrom()->id) : 0) , _history(App::history(_peer->id)) , _channel(peerToChannel(_peer->id)) -, _selMode(false) -, _rowsLeft(0) , _rowWidth(st::msgMinWidth) , _search(this, st::dlgFilter, lang(lng_dlg_filter)) , _cancelSearch(this, st::btnCancelSearch) , _itemsToBeLoaded(LinksOverviewPerPage * 2) -, _photosInRow(1) -, _inSearch(false) -, _searchFull(false) -, _searchFullMigrated(false) -, _searchRequest(0) -, _lastSearchId(0) -, _lastSearchMigratedId(0) -, _searchedCount(0) -, _width(st::wndMinWidth) -, _height(0) -, _minHeight(0) -, _marginTop(0) -, _marginBottom(0) -, _cursor(style::cur_default) -, _cursorState(HistoryDefaultCursorState) -, _dragAction(NoDrag) -, _dragItem(0) -, _selectedMsgId(0) -, _dragItemIndex(-1) -, _mousedItem(0) -, _mousedItemIndex(-1) -, _dragWasInactive(false) -, _dragSelFrom(0) -, _dragSelTo(0) -, _dragSelecting(false) -, _touchScroll(false) -, _touchSelect(false) -, _touchInProgress(false) -, _touchScrollState(TouchScrollManual) -, _touchPrevPosValid(false) -, _touchWaitingAcceleration(false) -, _touchSpeedTime(0) -, _touchAccelerationTime(0) -, _touchTime(0) -, _menu(0) { +, _width(st::wndMinWidth) { subscribe(FileDownload::ImageLoaded(), [this] { update(); }); + subscribe(Global::RefItemRemoved(), [this](HistoryItem *item) { + itemRemoved(item); + }); resize(_width, st::wndMinHeight); @@ -1733,6 +1698,10 @@ void OverviewInner::changingMsgId(HistoryItem *row, MsgId newId) { } void OverviewInner::itemRemoved(HistoryItem *item) { + if (_history != item->history() && _migrated != item->history()) { + return; + } + MsgId msgId = (item->history() == _migrated) ? -item->id : item->id; if (_dragItem == msgId) { dragActionCancel(); @@ -1741,13 +1710,13 @@ void OverviewInner::itemRemoved(HistoryItem *item) { _selectedMsgId = 0; } - SelectedItems::iterator i = _selected.find(msgId); + auto i = _selected.find(msgId); if (i != _selected.cend()) { _selected.erase(i); _overview->updateTopBarSelection(); } - LayoutItems::iterator j = _layoutItems.find(item); + auto j = _layoutItems.find(item); if (j != _layoutItems.cend()) { int32 index = _items.indexOf(j.value()); if (index >= 0) { @@ -2218,10 +2187,6 @@ void OverviewWidget::notify_historyItemLayoutChanged(const HistoryItem *item) { } } -void OverviewWidget::itemRemoved(HistoryItem *row) { - _inner.itemRemoved(row); -} - void OverviewWidget::fillSelectedItems(SelectedItemSet &sel, bool forDelete) { _inner.fillSelectedItems(sel, forDelete); } diff --git a/Telegram/SourceFiles/overviewwidget.h b/Telegram/SourceFiles/overviewwidget.h index e916a98d0..f43728545 100644 --- a/Telegram/SourceFiles/overviewwidget.h +++ b/Telegram/SourceFiles/overviewwidget.h @@ -36,7 +36,7 @@ class PlainShadow; } // namespace Ui class OverviewWidget; -class OverviewInner : public QWidget, public AbstractTooltipShower, public RPCSender, private base::Subscriber { +class OverviewInner : public TWidget, public AbstractTooltipShower, public RPCSender, private base::Subscriber { Q_OBJECT public: @@ -73,7 +73,6 @@ public: void mediaOverviewUpdated(); void changingMsgId(HistoryItem *row, MsgId newId); void repaintItem(const HistoryItem *msg); - void itemRemoved(HistoryItem *item); void getSelectionState(int32 &selectedForForward, int32 &selectedForDelete) const; void clearSelectedItems(bool onlyTextSelection = false); @@ -124,6 +123,7 @@ public slots: void onNeedSearchMessages(); private: + void itemRemoved(HistoryItem *item); MsgId complexMsgId(const HistoryItem *item) const; bool itemMigrated(MsgId msgId) const; @@ -152,7 +152,8 @@ private: OverviewWidget *_overview; ScrollArea *_scroll; - int32 _resizeIndex, _resizeSkip; + int _resizeIndex = -1; + int _resizeSkip = 0; PeerData *_peer; MediaOverviewType _type; @@ -160,10 +161,11 @@ private: History *_migrated, *_history; ChannelId _channel; - bool _selMode; + bool _selMode = false; TextSelection itemSelectedValue(int32 index) const; - int32 _rowsLeft, _rowWidth; + int _rowsLeft = 0; + int _rowWidth = 0; typedef QVector Items; Items _items; @@ -181,15 +183,18 @@ private: int32 _itemsToBeLoaded; // photos - int32 _photosInRow; + int32 _photosInRow = 1; QTimer _searchTimer; QString _searchQuery; - bool _inSearch, _searchFull, _searchFullMigrated; - mtpRequestId _searchRequest; + bool _inSearch = false; + bool _searchFull = false; + bool _searchFullMigrated = false; + mtpRequestId _searchRequest = 0; History::MediaOverview _searchResults; - MsgId _lastSearchId, _lastSearchMigratedId; - int32 _searchedCount; + MsgId _lastSearchId = 0; + MsgId _lastSearchMigratedId = 0; + int _searchedCount = 0; enum SearchRequestType { SearchFromStart, SearchFromOffset, @@ -205,13 +210,17 @@ private: typedef QMap SearchQueries; SearchQueries _searchQueries; - int32 _width, _height, _minHeight, _marginTop, _marginBottom; + int _width = 0; + int _height = 0; + int _minHeight = 0; + int _marginTop = 0; + int _marginBottom = 0; QTimer _linkTipTimer; // selection support, like in HistoryWidget - Qt::CursorShape _cursor; - HistoryCursorState _cursorState; + style::cursor _cursor = style::cur_default; + HistoryCursorState _cursorState = HistoryDefaultCursorState; using SelectedItems = QMap; SelectedItems _selected; enum DragAction { @@ -221,32 +230,40 @@ private: PrepareSelect = 0x03, Selecting = 0x04, }; - DragAction _dragAction; + DragAction _dragAction = NoDrag; QPoint _dragStartPos, _dragPos; - MsgId _dragItem, _selectedMsgId; - int32 _dragItemIndex; - MsgId _mousedItem; - int32 _mousedItemIndex; + MsgId _dragItem = 0; + MsgId _selectedMsgId = 0; + int _dragItemIndex = -1; + MsgId _mousedItem = 0; + int _mousedItemIndex = -1; uint16 _dragSymbol; - bool _dragWasInactive; + bool _dragWasInactive = false; ClickHandlerPtr _contextMenuLnk; - MsgId _dragSelFrom, _dragSelTo; - int32 _dragSelFromIndex, _dragSelToIndex; - bool _dragSelecting; + MsgId _dragSelFrom = 0; + MsgId _dragSelTo = 0; + int _dragSelFromIndex = -1; + int _dragSelToIndex = -1; + bool _dragSelecting = false; - bool _touchScroll, _touchSelect, _touchInProgress; + bool _touchScroll = false; + bool _touchSelect = false; + bool _touchInProgress = false; QPoint _touchStart, _touchPrevPos, _touchPos; QTimer _touchSelectTimer; - TouchScrollState _touchScrollState; - bool _touchPrevPosValid, _touchWaitingAcceleration; + TouchScrollState _touchScrollState = TouchScrollManual; + bool _touchPrevPosValid = false; + bool _touchWaitingAcceleration = false; QPoint _touchSpeed; - uint64 _touchSpeedTime, _touchAccelerationTime, _touchTime; + uint64 _touchSpeedTime = 0; + uint64 _touchAccelerationTime = 0; + uint64 _touchTime = 0; QTimer _touchScrollTimer; - PopupMenu *_menu; + PopupMenu *_menu = nullptr; }; class OverviewWidget : public TWidget, public RPCSender { diff --git a/Telegram/SourceFiles/settings/settings_notifications_widget.cpp b/Telegram/SourceFiles/settings/settings_notifications_widget.cpp index 6aa9c61b1..9aa824637 100644 --- a/Telegram/SourceFiles/settings/settings_notifications_widget.cpp +++ b/Telegram/SourceFiles/settings/settings_notifications_widget.cpp @@ -35,7 +35,7 @@ namespace Settings { NotificationsWidget::NotificationsWidget(QWidget *parent, UserData *self) : BlockWidget(parent, self, lang(lng_settings_section_notify)) { createControls(); - subscribe(Global::RefNotifySettingsChanged(), [this](const Notify::ChangeType &type) { + subscribe(Global::RefNotifySettingsChanged(), [this](Notify::ChangeType type) { if (type == Notify::ChangeType::DesktopEnabled) { desktopEnabledUpdated(); } else if (type == Notify::ChangeType::ViewParams) { diff --git a/Telegram/SourceFiles/title.cpp b/Telegram/SourceFiles/title.cpp index ab7a0f8a2..6ff6f77ee 100644 --- a/Telegram/SourceFiles/title.cpp +++ b/Telegram/SourceFiles/title.cpp @@ -103,18 +103,8 @@ TitleWidget::TitleWidget(QWidget *parent) : TWidget(parent) subscribe(Adaptive::Changed(), [this]() { updateAdaptiveLayout(); }); if (Media::Player::exists()) { - subscribe(Media::Player::instance()->createdNotifier(), [this](const Media::Player::PanelEvent &e) { - if (!_player) { - _player.create(this); - updateControlsVisibility(); - } - _player->installEventFilter(e.panel); - }); - subscribe(Media::Player::instance()->destroyedNotifier(), [this](const Media::Player::PanelEvent &e) { - if (_player) { - _player.destroyDelayed(); - updateControlsVisibility(); - } + subscribe(Media::Player::instance()->usePanelPlayer(), [this](bool usePanel) { + updatePlayerButton(usePanel); }); } @@ -179,6 +169,15 @@ void TitleWidget::onAbout() { Ui::showLayer(new AboutBox()); } +void TitleWidget::updatePlayerButton(bool usePanel) { + if (usePanel && !_player) { + _player.create(this); + } else if (!usePanel && _player) { + _player.destroyDelayed(); + } + updateControlsVisibility(); +} + void TitleWidget::updateControlsPosition() { QPoint p(width() - ((cPlatform() == dbipWindows && lastMaximized) ? 0 : st::sysBtnDelta), 0); diff --git a/Telegram/SourceFiles/title.h b/Telegram/SourceFiles/title.h index 43e7923e7..ed184a498 100644 --- a/Telegram/SourceFiles/title.h +++ b/Telegram/SourceFiles/title.h @@ -27,7 +27,6 @@ class MainWindow; namespace Media { namespace Player { class TitleButton; -class PanelEvent; } // namespace Player } // namespace Media class AudioMsgId; @@ -65,6 +64,7 @@ protected: void resizeEvent(QResizeEvent *e) override; private: + void updatePlayerButton(bool usePanel); void updateAdaptiveLayout(); void updateRestartButtonVisibility(); void updateMenuButtonsVisibility(); diff --git a/Telegram/SourceFiles/ui/widgets/continuous_slider.h b/Telegram/SourceFiles/ui/widgets/continuous_slider.h index a1dac0e40..cef44679c 100644 --- a/Telegram/SourceFiles/ui/widgets/continuous_slider.h +++ b/Telegram/SourceFiles/ui/widgets/continuous_slider.h @@ -39,6 +39,9 @@ public: void setValue(float64 value, bool animated); void setFadeOpacity(float64 opacity); void setDisabled(bool disabled); + bool isDisabled() const { + return _disabled; + } using Callback = base::lambda_unique; void setChangeProgressCallback(Callback &&callback) { @@ -71,9 +74,6 @@ protected: float64 getCurrentOverFactor(uint64 ms) { return _disabled ? 0. : _a_over.current(ms, _over ? 1. : 0.); } - bool isDisabled() const { - return _disabled; - } Direction getDirection() const { return _direction; } diff --git a/Telegram/SourceFiles/window/notifications_manager_default.cpp b/Telegram/SourceFiles/window/notifications_manager_default.cpp index 6fa37344b..bea419982 100644 --- a/Telegram/SourceFiles/window/notifications_manager_default.cpp +++ b/Telegram/SourceFiles/window/notifications_manager_default.cpp @@ -74,7 +74,7 @@ Manager::Manager() { notification->updatePeerPhoto(); } }); - subscribe(Global::RefNotifySettingsChanged(), [this](const Notify::ChangeType &change) { + subscribe(Global::RefNotifySettingsChanged(), [this](Notify::ChangeType change) { settingsChanged(change); }); _inputCheckTimer.setTimeoutHandler([this] { checkLastInput(); }); @@ -89,7 +89,7 @@ bool Manager::hasReplyingNotification() const { return false; } -void Manager::settingsChanged(const Notify::ChangeType &change) { +void Manager::settingsChanged(Notify::ChangeType change) { if (change == Notify::ChangeType::Corner) { auto startPosition = notificationStartPosition(); auto shiftDirection = notificationShiftDirection(); diff --git a/Telegram/SourceFiles/window/notifications_manager_default.h b/Telegram/SourceFiles/window/notifications_manager_default.h index 0181d85e0..228f4e62f 100644 --- a/Telegram/SourceFiles/window/notifications_manager_default.h +++ b/Telegram/SourceFiles/window/notifications_manager_default.h @@ -82,7 +82,7 @@ private: void moveWidgets(); void changeNotificationHeight(Notification *widget, int newHeight); - void settingsChanged(const Notify::ChangeType &change); + void settingsChanged(Notify::ChangeType change); bool hasReplyingNotification() const; diff --git a/Telegram/gyp/Telegram.gyp b/Telegram/gyp/Telegram.gyp index 5a39b4656..7b675db27 100644 --- a/Telegram/gyp/Telegram.gyp +++ b/Telegram/gyp/Telegram.gyp @@ -209,6 +209,7 @@ '<(src_loc)/core/single_timer.cpp', '<(src_loc)/core/single_timer.h', '<(src_loc)/core/stl_subset.h', + '<(src_loc)/core/type_traits.h', '<(src_loc)/core/utils.cpp', '<(src_loc)/core/utils.h', '<(src_loc)/core/vector_of_moveable.h',