From 61d335469f42cc09e9559fa568c26cafd714879b Mon Sep 17 00:00:00 2001 From: John Preston Date: Wed, 21 Oct 2020 17:41:13 +0300 Subject: [PATCH] Improve context menu in pinned section. --- Telegram/Resources/langs/lang.strings | 2 + .../history/history_inner_widget.cpp | 11 ++-- .../SourceFiles/history/history_widget.cpp | 38 ++---------- Telegram/SourceFiles/history/history_widget.h | 4 -- .../view/history_view_context_menu.cpp | 58 ++++++++++++++++++- .../history/view/history_view_element.h | 1 + .../history/view/history_view_message.cpp | 10 +++- .../view/history_view_pinned_section.cpp | 50 ++++++---------- .../view/history_view_pinned_section.h | 1 + .../view/history_view_top_bar_widget.cpp | 2 +- .../SourceFiles/window/window_peer_menu.cpp | 26 +++++++++ .../SourceFiles/window/window_peer_menu.h | 5 ++ 12 files changed, 127 insertions(+), 81 deletions(-) diff --git a/Telegram/Resources/langs/lang.strings b/Telegram/Resources/langs/lang.strings index 55fe15cf65..1aaf907696 100644 --- a/Telegram/Resources/langs/lang.strings +++ b/Telegram/Resources/langs/lang.strings @@ -316,6 +316,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL "lng_settings_events_title" = "Events"; "lng_settings_events_joined" = "Contact joined Telegram"; "lng_settings_events_pinned" = "Pinned messages"; +"lng_pinned_messages_title#one" = "{count} pinned message"; +"lng_pinned_messages_title#other" = "{count} pinned messages"; "lng_notification_preview" = "You have a new message"; "lng_notification_reply" = "Reply"; diff --git a/Telegram/SourceFiles/history/history_inner_widget.cpp b/Telegram/SourceFiles/history/history_inner_widget.cpp index a4fbfbb8b9..d819cb0e93 100644 --- a/Telegram/SourceFiles/history/history_inner_widget.cpp +++ b/Telegram/SourceFiles/history/history_inner_widget.cpp @@ -1572,13 +1572,10 @@ void HistoryInner::showContextMenu(QContextMenuEvent *e, bool showFromTouch) { } if (item->canPin()) { const auto isPinned = item->isPinned(); - _menu->addAction(isPinned ? tr::lng_context_unpin_msg(tr::now) : tr::lng_context_pin_msg(tr::now), [=] { - if (isPinned) { - _widget->unpinMessage(itemId); - } else { - _widget->pinMessage(itemId); - } - }); + const auto controller = _controller; + _menu->addAction(isPinned ? tr::lng_context_unpin_msg(tr::now) : tr::lng_context_pin_msg(tr::now), crl::guard(controller, [=] { + Window::ToggleMessagePinned(controller, itemId, !isPinned); + })); } }; const auto addPhotoActions = [&](not_null photo) { diff --git a/Telegram/SourceFiles/history/history_widget.cpp b/Telegram/SourceFiles/history/history_widget.cpp index 2a3bbe9182..de25e5ee22 100644 --- a/Telegram/SourceFiles/history/history_widget.cpp +++ b/Telegram/SourceFiles/history/history_widget.cpp @@ -5552,39 +5552,6 @@ void HistoryWidget::editMessage(not_null item) { _field->setFocus(); } -void HistoryWidget::pinMessage(FullMsgId itemId) { - if (const auto item = session().data().message(itemId)) { - if (item->canPin()) { - Ui::show(Box(item->history()->peer, item->id)); - } - } -} - -void HistoryWidget::unpinMessage(FullMsgId itemId) { - if (!_peer) { - return; - } - UnpinMessage(_peer, itemId.msg); -} - -void HistoryWidget::UnpinMessage(not_null peer, MsgId msgId) { - if (!peer) { - return; - } - - const auto session = &peer->session(); - Ui::show(Box(tr::lng_pinned_unpin_sure(tr::now), tr::lng_pinned_unpin(tr::now), crl::guard(session, [=] { - Ui::hideLayer(); - session->api().request(MTPmessages_UpdatePinnedMessage( - MTP_flags(MTPmessages_UpdatePinnedMessage::Flag::f_unpin), - peer->input, - MTP_int(msgId) - )).done([=](const MTPUpdates &result) { - session->api().applyUpdates(result); - }).send(); - }))); -} - void HistoryWidget::hidePinnedMessage() { Expects(_pinnedBar != nullptr); @@ -5593,7 +5560,10 @@ void HistoryWidget::hidePinnedMessage() { return; } if (_peer->canPinMessages()) { - unpinMessage({ peerToChannel(_peer->id), id.message }); + Window::ToggleMessagePinned( + controller(), + { peerToChannel(_peer->id), id.message }, + false); } else { const auto top = Data::ResolveTopPinnedId(_peer); if (top) { diff --git a/Telegram/SourceFiles/history/history_widget.h b/Telegram/SourceFiles/history/history_widget.h index 4d72f0f320..197e63176b 100644 --- a/Telegram/SourceFiles/history/history_widget.h +++ b/Telegram/SourceFiles/history/history_widget.h @@ -183,8 +183,6 @@ public: void replyToMessage(not_null item); void editMessage(FullMsgId itemId); void editMessage(not_null item); - void pinMessage(FullMsgId itemId); - void unpinMessage(FullMsgId itemId); MsgId replyToId() const; bool lastForceReplyReplied(const FullMsgId &replyTo) const; @@ -517,8 +515,6 @@ private: void addMessagesToFront(PeerData *peer, const QVector &messages); void addMessagesToBack(PeerData *peer, const QVector &messages); - static void UnpinMessage(not_null peer, MsgId msgId); - void updateHistoryGeometry(bool initial = false, bool loadedDown = false, const ScrollChange &change = { ScrollChangeNone, 0 }); void updateListSize(); diff --git a/Telegram/SourceFiles/history/view/history_view_context_menu.cpp b/Telegram/SourceFiles/history/view/history_view_context_menu.cpp index c4b5d101d5..c1feda60f5 100644 --- a/Telegram/SourceFiles/history/view/history_view_context_menu.cpp +++ b/Telegram/SourceFiles/history/view/history_view_context_menu.cpp @@ -496,10 +496,12 @@ bool AddReplyToMessageAction( not_null menu, const ContextMenuRequest &request, not_null list) { + const auto context = list->elementContext(); const auto item = request.item; if (!item || !IsServerMsgId(item->id) - || !item->history()->peer->canWrite()) { + || !item->history()->peer->canWrite() + || (context != Context::History && context != Context::Replies)) { return false; } const auto owner = &item->history()->owner(); @@ -514,6 +516,37 @@ bool AddReplyToMessageAction( return true; } +bool AddViewRepliesAction( + not_null menu, + const ContextMenuRequest &request, + not_null list) { + const auto context = list->elementContext(); + const auto item = request.item; + if (!item + || !IsServerMsgId(item->id) + || (context != Context::History && context != Context::Pinned)) { + return false; + } + const auto repliesCount = item->repliesCount(); + const auto withReplies = (repliesCount > 0); + if (!withReplies || !item->history()->peer->isMegagroup()) { + return false; + } + const auto rootId = repliesCount ? item->id : item->replyToTop(); + const auto phrase = (repliesCount > 0) + ? tr::lng_replies_view( + tr::now, + lt_count, + repliesCount) + : tr::lng_replies_view_thread(tr::now); + const auto controller = list->controller(); + const auto history = item->history(); + menu->addAction(phrase, crl::guard(controller, [=] { + controller->showRepliesForMessage(history, rootId); + })); + return true; +} + bool AddEditMessageAction( not_null menu, const ContextMenuRequest &request, @@ -537,6 +570,27 @@ bool AddEditMessageAction( return true; } +bool AddPinMessageAction( + not_null menu, + const ContextMenuRequest &request, + not_null list) { + const auto context = list->elementContext(); + const auto item = request.item; + if (!item + || !IsServerMsgId(item->id) + || !item->canPin() + || (context != Context::History && context != Context::Pinned)) { + return false; + } + const auto itemId = item->fullId(); + const auto isPinned = item->isPinned(); + const auto controller = list->controller(); + menu->addAction(isPinned ? tr::lng_context_unpin_msg(tr::now) : tr::lng_context_pin_msg(tr::now), crl::guard(controller, [=] { + Window::ToggleMessagePinned(controller, itemId, !isPinned); + })); + return true; +} + void AddSendNowAction( not_null menu, const ContextMenuRequest &request, @@ -720,7 +774,9 @@ void AddTopMessageActions( const ContextMenuRequest &request, not_null list) { AddReplyToMessageAction(menu, request, list); + AddViewRepliesAction(menu, request, list); AddEditMessageAction(menu, request, list); + AddPinMessageAction(menu, request, list); } void AddMessageActions( diff --git a/Telegram/SourceFiles/history/view/history_view_element.h b/Telegram/SourceFiles/history/view/history_view_element.h index 05aadbcdcb..8007612402 100644 --- a/Telegram/SourceFiles/history/view/history_view_element.h +++ b/Telegram/SourceFiles/history/view/history_view_element.h @@ -33,6 +33,7 @@ class Media; enum class Context : char { History, Replies, + Pinned, //Feed, // #feed AdminLog, ContactPreview diff --git a/Telegram/SourceFiles/history/view/history_view_message.cpp b/Telegram/SourceFiles/history/view/history_view_message.cpp index 1eaf6786a5..d909a839d5 100644 --- a/Telegram/SourceFiles/history/view/history_view_message.cpp +++ b/Telegram/SourceFiles/history/view/history_view_message.cpp @@ -1214,6 +1214,7 @@ bool Message::hasFromPhoto() const { //case Context::Feed: // #feed return true; case Context::History: + case Context::Pinned: case Context::Replies: { const auto item = message(); if (item->isPost() @@ -2051,6 +2052,7 @@ bool Message::hasFromName() const { //case Context::Feed: // #feed return true; case Context::History: + case Context::Pinned: case Context::Replies: { const auto item = message(); return (!hasOutLayout() || item->from()->isMegagroup()) @@ -2216,6 +2218,9 @@ bool Message::displayFastShare() const { } bool Message::displayGoToOriginal() const { + if (context() == Context::Pinned) { + return true; + } const auto item = message(); if (const auto forwarded = item->Get()) { return forwarded->savedFromPeer @@ -2277,7 +2282,10 @@ void Message::drawRightAction( ClickHandlerPtr Message::rightActionLink() const { if (!_rightActionLink) { - if (displayRightActionComments()) { + if (context() == Context::Pinned) { + _rightActionLink = goToMessageClickHandler(data()); + return _rightActionLink; + } else if (displayRightActionComments()) { _rightActionLink = createGoToCommentsLink(); return _rightActionLink; } diff --git a/Telegram/SourceFiles/history/view/history_view_pinned_section.cpp b/Telegram/SourceFiles/history/view/history_view_pinned_section.cpp index d6c6ac3ad5..767e1c58fe 100644 --- a/Telegram/SourceFiles/history/view/history_view_pinned_section.cpp +++ b/Telegram/SourceFiles/history/view/history_view_pinned_section.cpp @@ -102,6 +102,7 @@ PinnedWidget::PinnedWidget( _topBar->move(0, 0); _topBar->resizeToWidth(width()); _topBar->show(); + _topBar->setCustomTitle(tr::lng_contacts_loading(tr::now)); _topBar->deleteSelectionRequest( ) | rpl::start_with_next([=] { @@ -285,10 +286,7 @@ QPixmap PinnedWidget::grabForShowAnimation(const Window::SectionSlideParams &par } void PinnedWidget::doSetInnerFocus() { - if (!_inner->getSelectedText().rich.text.isEmpty() - || !_inner->getSelectedItems().empty()) { - _inner->setFocus(); - } + _inner->setFocus(); } bool PinnedWidget::showInternal( @@ -321,33 +319,7 @@ bool PinnedWidget::showMessage( PeerId peerId, const Window::SectionShow ¶ms, MsgId messageId) { - if (peerId != _history->peer->id) { - return false; - } - const auto id = FullMsgId{ - _history->channelId(), - messageId - }; - const auto message = _history->owner().message(id); - if (!message || !message->isPinned()) { - return false; - } - - const auto originItem = [&]() -> HistoryItem* { - using OriginMessage = Window::SectionShow::OriginMessage; - if (const auto origin = std::get_if(¶ms.origin)) { - if (const auto returnTo = session().data().message(origin->id)) { - if (returnTo->history() == _history && returnTo->isPinned()) { - return returnTo; - } - } - } - return nullptr; - }(); - showAtPosition( - Data::MessagePosition{ .fullId = id, .date = message->date() }, - originItem); - return true; + return false; // We want 'Go to original' to work. } void PinnedWidget::saveState(not_null memento) { @@ -463,7 +435,7 @@ QRect PinnedWidget::floatPlayerAvailableRect() { } Context PinnedWidget::listContext() { - return Context::Replies; + return Context::Pinned; } void PinnedWidget::listScrollTo(int top) { @@ -502,7 +474,19 @@ rpl::producer PinnedWidget::listSource( messageId), limitBefore, limitAfter - ) | rpl::map([=](SparseIdsSlice &&slice) { + ) | rpl::filter([=](const SparseIdsSlice &slice) { + const auto count = slice.fullCount(); + if (!count.has_value()) { + return true; + } else if (*count != 0) { + _topBar->setCustomTitle( + tr::lng_pinned_messages_title(tr::now, lt_count, *count)); + return true; + } else { + controller()->showBackFromStack(); + return false; + } + }) | rpl::map([=](SparseIdsSlice &&slice) { auto result = Data::MessagesSlice(); result.fullCount = slice.fullCount(); result.skippedAfter = slice.skippedAfter(); diff --git a/Telegram/SourceFiles/history/view/history_view_pinned_section.h b/Telegram/SourceFiles/history/view/history_view_pinned_section.h index c5eebcf5e5..a3d5dd56a2 100644 --- a/Telegram/SourceFiles/history/view/history_view_pinned_section.h +++ b/Telegram/SourceFiles/history/view/history_view_pinned_section.h @@ -138,6 +138,7 @@ private: bool _skipScrollEvent = false; std::unique_ptr _scroll; + object_ptr _clearButton = { nullptr }; Ui::Animations::Simple _scrollDownShown; bool _scrollDownIsShown = false; diff --git a/Telegram/SourceFiles/history/view/history_view_top_bar_widget.cpp b/Telegram/SourceFiles/history/view/history_view_top_bar_widget.cpp index d6bb60e7de..6de1fb6440 100644 --- a/Telegram/SourceFiles/history/view/history_view_top_bar_widget.cpp +++ b/Telegram/SourceFiles/history/view/history_view_top_bar_widget.cpp @@ -343,7 +343,7 @@ void TopBarWidget::paintTopBar(Painter &p) { ? tr::lng_reminder_messages(tr::now) : tr::lng_scheduled_messages(tr::now)) : (_section == Section::Pinned) - ? "Pinned messages" // #TODO pinned + ? _customTitleText : folder ? folder->chatListName() : history->peer->isSelf() diff --git a/Telegram/SourceFiles/window/window_peer_menu.cpp b/Telegram/SourceFiles/window/window_peer_menu.cpp index 3bc19bb242..6bf313f7ad 100644 --- a/Telegram/SourceFiles/window/window_peer_menu.cpp +++ b/Telegram/SourceFiles/window/window_peer_menu.cpp @@ -1124,6 +1124,32 @@ void PeerMenuAddChannelMembers( })); } +void ToggleMessagePinned( + not_null navigation, + FullMsgId itemId, + bool pin) { + const auto item = navigation->session().data().message(itemId); + if (!item || !item->canPin()) { + return; + } + if (pin) { + Ui::show(Box(item->history()->peer, item->id)); + } else { + const auto peer = item->history()->peer; + const auto session = &peer->session(); + Ui::show(Box(tr::lng_pinned_unpin_sure(tr::now), tr::lng_pinned_unpin(tr::now), crl::guard(session, [=] { + Ui::hideLayer(); + session->api().request(MTPmessages_UpdatePinnedMessage( + MTP_flags(MTPmessages_UpdatePinnedMessage::Flag::f_unpin), + peer->input, + MTP_int(itemId.msg) + )).done([=](const MTPUpdates &result) { + session->api().applyUpdates(result); + }).send(); + }))); + } +} + void PeerMenuAddMuteAction( not_null peer, const PeerMenuCallback &addAction) { diff --git a/Telegram/SourceFiles/window/window_peer_menu.h b/Telegram/SourceFiles/window/window_peer_menu.h index 52706de669..7bbfc7c8ed 100644 --- a/Telegram/SourceFiles/window/window_peer_menu.h +++ b/Telegram/SourceFiles/window/window_peer_menu.h @@ -111,4 +111,9 @@ QPointer ShowSendNowMessagesBox( MessageIdsList &&items, FnMut &&successCallback = nullptr); +void ToggleMessagePinned( + not_null navigation, + FullMsgId itemId, + bool pin); + } // namespace Window