diff --git a/Telegram/CMakeLists.txt b/Telegram/CMakeLists.txt index 0c4e4c2162..d3e757a5d6 100644 --- a/Telegram/CMakeLists.txt +++ b/Telegram/CMakeLists.txt @@ -880,6 +880,8 @@ PRIVATE history/view/reactions/history_view_reactions_strip.h history/view/reactions/history_view_reactions_tabs.cpp history/view/reactions/history_view_reactions_tabs.h + history/view/history_view_top_peers_selector.cpp + history/view/history_view_top_peers_selector.h history/view/history_view_about_view.cpp history/view/history_view_about_view.h history/view/history_view_bottom_info.cpp diff --git a/Telegram/SourceFiles/chat_helpers/chat_helpers.style b/Telegram/SourceFiles/chat_helpers/chat_helpers.style index 02ecf89ba7..1354506f5a 100644 --- a/Telegram/SourceFiles/chat_helpers/chat_helpers.style +++ b/Telegram/SourceFiles/chat_helpers/chat_helpers.style @@ -1747,4 +1747,7 @@ menuTranscribeDummyButton: IconButton(defaultIconButton) { roundVideoFont: font(14px semibold); +topPeersSelectorUserpicSize: 30px; +topPeersSelectorUserpicGap: 8px; +topPeersSelectorPadding: 6px; topPeersSelectorUserpicExpand: 0.1; diff --git a/Telegram/SourceFiles/history/view/history_view_top_peers_selector.cpp b/Telegram/SourceFiles/history/view/history_view_top_peers_selector.cpp new file mode 100644 index 0000000000..a599aa3af0 --- /dev/null +++ b/Telegram/SourceFiles/history/view/history_view_top_peers_selector.cpp @@ -0,0 +1,124 @@ +// This file is part of Telegram Desktop, +// the official desktop application for the Telegram messaging service. +// +// For license and copyright information please follow this link: +// https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL +// +#include "history/view/history_view_top_peers_selector.h" + +#include "apiwrap.h" +#include "main/session/session_show.h" +#include "chat_helpers/share_message_phrase_factory.h" +#include "ui/controls/dynamic_images_strip.h" +#include "ui/controls/popup_selector.h" +#include "ui/dynamic_image.h" +#include "ui/dynamic_thumbnails.h" +#include "ui/effects/animations.h" +#include "ui/rect.h" +#include "data/components/top_peers.h" +#include "history/history.h" +#include "data/data_peer.h" +#include "data/data_user.h" +#include "data/data_session.h" +#include "main/main_session.h" +#include "styles/style_chat_helpers.h" + +namespace HistoryView { +namespace { + +constexpr auto kMaxPeers = 5; + +[[nodiscard]] std::vector> CollectPeers( + not_null session) { + const auto user = session->user(); + auto topPeers = session->topPeers().list(); + const auto it = ranges::find(topPeers, user); + if (it != topPeers.end()) { + topPeers.erase(it); + } + auto result = std::vector>(); + result.push_back(user); + for (const auto &peer : topPeers | ranges::views::take(kMaxPeers - 1)) { + result.push_back(peer); + } + return result; +} + +} // namespace + +void ShowTopPeersSelector( + not_null parent, + std::shared_ptr show, + FullMsgId fullId) { + const auto session = &show->session(); + const auto peers = CollectPeers(session); + auto thumbnails = std::vector>(); + thumbnails.reserve(peers.size()); + for (const auto &peer : peers) { + thumbnails.push_back(peer->isSelf() + ? Ui::MakeSavedMessagesThumbnail() + : Ui::MakeUserpicThumbnail(peer)); + } + + const auto send = [=](not_null peer) { + if (const auto item = session->data().message(fullId)) { + session->api().forwardMessages( + Data::ResolvedForwardDraft{ .items = { item } }, + Api::SendAction(session->data().history(peer)), + [=] { + using namespace ChatHelpers; + auto text = rpl::variable( + ForwardedMessagePhrase({ + .toCount = 1, + .singleMessage = 1, + .to1 = peer, + })).current(); + show->showToast(std::move(text)); + }); + } + }; + + const auto contentWidth = peers.size() * st::topPeersSelectorUserpicSize + + (peers.size() - 1) * st::topPeersSelectorUserpicGap; + const auto contentHeight = int( + st::topPeersSelectorUserpicSize + * (1. + st::topPeersSelectorUserpicExpand)); + const auto selectorWidth = contentWidth + + 2 * st::topPeersSelectorPadding; + const auto selectorHeight = contentHeight + + 2 * st::topPeersSelectorPadding; + const auto selector = Ui::CreateChild( + parent, + QSize(selectorWidth, selectorHeight)); + const auto userpicsWidget = Ui::CreateChild( + selector, + std::move(thumbnails), + st::topPeersSelectorUserpicSize, + st::topPeersSelectorUserpicGap); + const auto margins = selector->marginsForShadow(); + const auto x = (selectorWidth - contentWidth) / 2 + margins.left(); + const auto y = (selectorHeight - contentHeight) / 2 + margins.top(); + userpicsWidget->setGeometry( + QRect(x, y, contentWidth, contentHeight) + + Margins(int(st::topPeersSelectorUserpicSize + * st::topPeersSelectorUserpicExpand))); + userpicsWidget->setClickCallback([=](int index) { + send(peers[index]); + selector->hideAnimated(); + }); + userpicsWidget->setCursor(style::cur_pointer); + selector->updateShowState(0, 0, true); + selector->popup(QCursor::pos()); + + auto animation + = selector->lifetime().make_state(); + constexpr auto kShift = 0.15; + animation->start([=](float64 value) { + const auto userpicsProgress = std::clamp((value - kShift), 0., 1.); + userpicsWidget->setProgress(anim::easeInQuint(1, userpicsProgress)); + value = std::clamp(value, 0., 1.); + selector->updateShowState(value, value, true); + }, 0., 1. + kShift, st::fadeWrapDuration * 3, anim::easeOutQuint); +} + +} // namespace HistoryView diff --git a/Telegram/SourceFiles/history/view/history_view_top_peers_selector.h b/Telegram/SourceFiles/history/view/history_view_top_peers_selector.h new file mode 100644 index 0000000000..f1bd9588a5 --- /dev/null +++ b/Telegram/SourceFiles/history/view/history_view_top_peers_selector.h @@ -0,0 +1,24 @@ +// This file is part of Telegram Desktop, +// the official desktop application for the Telegram messaging service. +// +// For license and copyright information please follow this link: +// https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL +// +#pragma once + +namespace Ui { +class RpWidget; +} // namespace Ui + +namespace Main { +class SessionShow; +} // namespace Main + +namespace HistoryView { + +void ShowTopPeersSelector( + not_null parent, + std::shared_ptr show, + FullMsgId fullId); + +} // namespace HistoryView