From e6c2aa8021271b79a3f377bea720a9c2910f61d2 Mon Sep 17 00:00:00 2001 From: John Preston Date: Tue, 1 Nov 2022 15:17:13 +0400 Subject: [PATCH] Support topic choosing in ShareBox. --- .../boxes/peers/edit_peer_invite_link.cpp | 19 +- Telegram/SourceFiles/boxes/share_box.cpp | 278 +++++++++++++----- Telegram/SourceFiles/boxes/share_box.h | 9 +- .../calls/group/calls_group_settings.cpp | 19 +- .../SourceFiles/history/history_message.cpp | 7 + .../SourceFiles/history/history_message.h | 4 + .../controls/history_view_forward_panel.cpp | 2 +- .../view/history_view_pinned_section.cpp | 6 +- .../view/history_view_pinned_tracker.cpp | 2 +- .../inline_bots/bot_attach_web_view.cpp | 2 +- Telegram/SourceFiles/mainwidget.cpp | 2 +- .../SourceFiles/ui/effects/round_checkbox.cpp | 24 +- .../SourceFiles/ui/effects/round_checkbox.h | 8 +- .../SourceFiles/window/window_peer_menu.cpp | 8 +- 14 files changed, 273 insertions(+), 117 deletions(-) diff --git a/Telegram/SourceFiles/boxes/peers/edit_peer_invite_link.cpp b/Telegram/SourceFiles/boxes/peers/edit_peer_invite_link.cpp index eb8819fde..569d57c6b 100644 --- a/Telegram/SourceFiles/boxes/peers/edit_peer_invite_link.cpp +++ b/Telegram/SourceFiles/boxes/peers/edit_peer_invite_link.cpp @@ -1141,7 +1141,7 @@ object_ptr ShareInviteLinkBox( showToast(tr::lng_group_invite_copied(tr::now)); }; auto submitCallback = [=]( - std::vector> &&result, + std::vector> &&result, TextWithTags &&comment, Api::SendOptions options, Data::ForwardOptions) { @@ -1150,12 +1150,12 @@ object_ptr ShareInviteLinkBox( } const auto error = [&] { - for (const auto peer : result) { + for (const auto thread : result) { const auto error = GetErrorTextForSending( - peer, + thread, { .text = &comment }); if (!error.isEmpty()) { - return std::make_pair(error, peer); + return std::make_pair(error, thread); } } return std::make_pair(QString(), result.front()); @@ -1164,7 +1164,7 @@ object_ptr ShareInviteLinkBox( auto text = TextWithEntities(); if (result.size() > 1) { text.append( - Ui::Text::Bold(error.second->name()) + Ui::Text::Bold(error.second->chatListName()) ).append("\n\n"); } text.append(error.first); @@ -1188,10 +1188,9 @@ object_ptr ShareInviteLinkBox( } const auto owner = &peer->owner(); auto &api = peer->session().api(); - for (const auto peer : result) { - const auto history = owner->history(peer); + for (const auto thread : result) { auto message = Api::MessageToSend( - Api::SendAction(history, options)); + Api::SendAction(thread, options)); message.textWithTags = comment; message.action.clearDraft = false; api.sendMessage(std::move(message)); @@ -1204,8 +1203,8 @@ object_ptr ShareInviteLinkBox( auto object = Box(ShareBox::Descriptor{ .session = &peer->session(), .copyCallback = std::move(copyCallback), - .submitCallback = std::move(submitCallback), // #TODO forum share - .filterCallback = [](auto peer) { return peer->canWrite(); }, + .submitCallback = std::move(submitCallback), + .filterCallback = [](auto thread) { return thread->canWrite(); }, }); *box = Ui::MakeWeak(object.data()); return object; diff --git a/Telegram/SourceFiles/boxes/share_box.cpp b/Telegram/SourceFiles/boxes/share_box.cpp index 278e46c76..d929f9bdf 100644 --- a/Telegram/SourceFiles/boxes/share_box.cpp +++ b/Telegram/SourceFiles/boxes/share_box.cpp @@ -35,7 +35,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "history/view/history_view_context_menu.h" // CopyPostLink. #include "history/view/history_view_schedule_box.h" #include "window/window_session_controller.h" -#include "boxes/peer_list_box.h" +#include "boxes/peer_list_controllers.h" #include "chat_helpers/emoji_suggestions_widget.h" #include "data/data_channel.h" #include "data/data_game.h" @@ -43,6 +43,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "data/data_user.h" #include "data/data_session.h" #include "data/data_folder.h" +#include "data/data_forum.h" +#include "data/data_forum_topic.h" #include "data/data_changes.h" #include "main/main_session.h" #include "core/application.h" @@ -57,14 +59,17 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL class ShareBox::Inner final : public Ui::RpWidget { public: - Inner(QWidget *parent, const Descriptor &descriptor); + Inner( + QWidget *parent, + const Descriptor &descriptor, + std::shared_ptr show); void setPeerSelectedChangedCallback( - Fn callback); + Fn thread, bool selected)> callback); void peerUnselected(not_null peer); - std::vector> selected() const; - bool hasSelected() const; + [[nodiscard]] std::vector> selected() const; + [[nodiscard]] bool hasSelected() const; void peopleReceived( const QString &query, @@ -95,11 +100,13 @@ protected: private: struct Chat { Chat( - PeerData *peer, + not_null peer, const style::PeerListItem &st, Fn updateCallback); - PeerData *peer; + not_null peer; + Data::ForumTopic *topic = nullptr; + rpl::lifetime topicLifetime; Ui::RoundImageCheckbox checkbox; Ui::Text::String name; Ui::Animations::Simple nameActive; @@ -107,11 +114,13 @@ private: void invalidateCache(); - int displayedChatsCount() const; + [[nodiscard]] int displayedChatsCount() const; + [[nodiscard]] not_null chatThread( + not_null chat) const; void paintChat(Painter &p, not_null chat, int index); void updateChat(not_null peer); - void updateChatName(not_null chat, not_null peer); + void updateChatName(not_null chat); void repaintChat(not_null peer); int chatIndex(not_null peer) const; void repaintChatAtIndex(int index); @@ -119,6 +128,7 @@ private: void loadProfilePhotos(int yFrom); void changeCheckState(Chat *chat); + void chooseForumTopic(not_null forum); enum class ChangeStateWay { Default, SkipCallback, @@ -135,6 +145,7 @@ private: void refresh(); const Descriptor &_descriptor; + const std::shared_ptr _show; const style::PeerList &_st; float64 _columnSkip = 0.; @@ -152,9 +163,9 @@ private: std::vector> _filtered; std::map, std::unique_ptr> _dataMap; - base::flat_set> _selected; + base::flat_set> _selected; - Fn _peerSelectedChangedCallback; + Fn, bool)> _peerSelectedChangedCallback; bool _searching = false; QString _lastQuery; @@ -247,7 +258,7 @@ void ShareBox::prepare() { setTitle(tr::lng_share_title()); _inner = setInnerWidget( - object_ptr(this, _descriptor), + object_ptr(this, _descriptor, _show), getTopScrollSkip(), getBottomScrollSkip()); @@ -293,8 +304,10 @@ void ShareBox::prepare() { scrollTo(request); }, _inner->lifetime()); - _inner->setPeerSelectedChangedCallback([=](PeerData *peer, bool checked) { - innerSelectedChanged(peer, checked); + _inner->setPeerSelectedChangedCallback([=]( + not_null thread, + bool checked) { + innerSelectedChanged(thread, checked); }); Ui::Emoji::SuggestionsController::Init( @@ -442,9 +455,11 @@ void ShareBox::keyPressEvent(QKeyEvent *e) { SendMenu::Type ShareBox::sendMenuType() const { const auto selected = _inner->selected(); - return ranges::all_of(selected, HistoryView::CanScheduleUntilOnline) + return ranges::all_of( + selected | ranges::views::transform(&Data::Thread::peer), + HistoryView::CanScheduleUntilOnline) ? SendMenu::Type::ScheduledToUser - : (selected.size() == 1 && selected.front()->isSelf()) + : (selected.size() == 1 && selected.front()->peer()->isSelf()) ? SendMenu::Type::Reminder : SendMenu::Type::Scheduled; } @@ -522,23 +537,51 @@ void ShareBox::applyFilterUpdate(const QString &query) { _inner->updateFilter(query); } -void ShareBox::addPeerToMultiSelect(PeerData *peer, bool skipAnimation) { - using AddItemWay = Ui::MultiSelect::AddItemWay; - auto addItemWay = skipAnimation ? AddItemWay::SkipAnimation : AddItemWay::Default; +PaintRoundImageCallback ForceRoundUserpicCallback(not_null peer) { + auto userpic = std::shared_ptr(); + auto cache = std::make_shared(); + return [=](Painter &p, int x, int y, int outerWidth, int size) mutable { + const auto ratio = style::DevicePixelRatio(); + const auto cacheSize = QSize(size, size) * ratio; + if (cache->size() != cacheSize) { + *cache = QImage(cacheSize, QImage::Format_ARGB32_Premultiplied); + cache->setDevicePixelRatio(ratio); + } + auto q = Painter(cache.get()); + peer->paintUserpicLeft(q, userpic, 0, 0, outerWidth, size); + q.end(); + + *cache = Images::Circle(std::move(*cache)); + p.drawImage(x, y, *cache); + }; +} + +void ShareBox::addPeerToMultiSelect(not_null thread) { + auto addItemWay = Ui::MultiSelect::AddItemWay::Default; + const auto peer = thread->peer(); + const auto topic = thread->asTopic(); _select->addItem( peer->id.value, - peer->isSelf() ? tr::lng_saved_short(tr::now) : peer->shortName(), + (topic + ? topic->title() + : peer->isSelf() + ? tr::lng_saved_short(tr::now) + : peer->shortName()), st::activeButtonBg, - PaintUserpicCallback(peer, true), + (topic + ? ForceRoundUserpicCallback(peer) + : PaintUserpicCallback(peer, true)), addItemWay); } -void ShareBox::innerSelectedChanged(PeerData *peer, bool checked) { +void ShareBox::innerSelectedChanged( + not_null thread, + bool checked) { if (checked) { - addPeerToMultiSelect(peer); + addPeerToMultiSelect(thread); _select->clearQuery(); } else { - _select->removeItem(peer->id.value); + _select->removeItem(thread->peer()->id.value); } selectedChanged(); update(); @@ -612,9 +655,13 @@ void ShareBox::scrollAnimationCallback() { //scrollArea()->scrollToY(scrollTop); } -ShareBox::Inner::Inner(QWidget *parent, const Descriptor &descriptor) +ShareBox::Inner::Inner( + QWidget *parent, + const Descriptor &descriptor, + std::shared_ptr show) : RpWidget(parent) , _descriptor(descriptor) +, _show(std::move(show)) , _st(_descriptor.st ? *_descriptor.st : st::shareBoxList) , _chatsIndexed( std::make_unique( @@ -624,14 +671,16 @@ ShareBox::Inner::Inner(QWidget *parent, const Descriptor &descriptor) setAttribute(Qt::WA_OpaquePaintEvent); const auto self = _descriptor.session->user(); - if (_descriptor.filterCallback(self)) { - _chatsIndexed->addToEnd(self->owner().history(self)); + const auto selfHistory = self->owner().history(self); + if (_descriptor.filterCallback(selfHistory)) { + _chatsIndexed->addToEnd(selfHistory); } const auto addList = [&](not_null list) { for (const auto &row : list->all()) { if (const auto history = row->history()) { if (!history->peer->isSelf() - && _descriptor.filterCallback(history->peer)) { + && (history->asForum() + || _descriptor.filterCallback(history))) { _chatsIndexed->addToEnd(history); } } @@ -715,15 +764,16 @@ void ShareBox::Inner::activateSkipPage(int pageHeight, int direction) { void ShareBox::Inner::updateChat(not_null peer) { if (const auto i = _dataMap.find(peer); i != end(_dataMap)) { - updateChatName(i->second.get(), peer); + updateChatName(i->second.get()); repaintChat(peer); } } -void ShareBox::Inner::updateChatName( - not_null chat, - not_null peer) { - const auto text = peer->isSelf() +void ShareBox::Inner::updateChatName(not_null chat) { + const auto peer = chat->peer; + const auto text = chat->topic + ? chat->topic->title() + : peer->isSelf() ? tr::lng_saved_messages(tr::now) : peer->isRepliesChat() ? tr::lng_replies_messages(tr::now) @@ -852,7 +902,7 @@ auto ShareBox::Inner::getChat(not_null row) const auto [i, ok] = _dataMap.emplace( peer, std::make_unique(peer, _st.item, [=] { repaintChat(peer); })); - updateChatName(i->second.get(), peer); + updateChatName(i->second.get()); row->attached = i->second.get(); return i->second.get(); } @@ -896,11 +946,17 @@ void ShareBox::Inner::paintChat( } ShareBox::Inner::Chat::Chat( - PeerData *peer, + not_null peer, const style::PeerListItem &st, Fn updateCallback) : peer(peer) -, checkbox(st.checkbox, updateCallback, PaintUserpicCallback(peer, true)) +, checkbox( + st.checkbox, + updateCallback, + PaintUserpicCallback(peer, true), + [=] { return peer->isForum() + ? ImageRoundRadius::Large + : ImageRoundRadius::Ellipse; }) , name(st.checkbox.imageRadius * 2) { } @@ -1022,9 +1078,9 @@ void ShareBox::Inner::resizeEvent(QResizeEvent *e) { } void ShareBox::Inner::changeCheckState(Chat *chat) { - if (!chat) return; - - if (!_filter.isEmpty()) { + if (!chat) { + return; + } else if (!_filter.isEmpty()) { const auto history = chat->peer->owner().history(chat->peer); auto row = _chatsIndexed->getRow(history); if (!row) { @@ -1036,7 +1092,60 @@ void ShareBox::Inner::changeCheckState(Chat *chat) { } } - changePeerCheckState(chat, !chat->checkbox.checked()); + const auto checked = chat->checkbox.checked(); + const auto forum = chat->peer->forum(); + if (checked || !forum) { + changePeerCheckState(chat, !checked); + } else { + chooseForumTopic(chat->peer->forum()); + } +} + +void ShareBox::Inner::chooseForumTopic(not_null forum) { + const auto guard = Ui::MakeWeak(this); + const auto weak = std::make_shared>(); + auto chosen = [=](not_null topic) { + if (const auto strong = *weak) { + strong->closeBox(); + } + if (!guard) { + return; + } + const auto row = _chatsIndexed->getRow(topic->owningHistory()); + if (!row) { + return; + } + const auto chat = getChat(row); + Assert(!chat->topic); + chat->topic = topic; + chat->topic->destroyed( + ) | rpl::start_with_next([=] { + changePeerCheckState(chat, false); + }, chat->topicLifetime); + updateChatName(chat); + changePeerCheckState(chat, true); + }; + auto initBox = [](not_null box) { + box->addButton(tr::lng_cancel(), [box] { + box->closeBox(); + }); + }; + auto box = Box( + std::make_unique( + forum, + std::move(chosen)), + [=](not_null box) { + box->addButton(tr::lng_cancel(), [=] { + box->closeBox(); + }); + + forum->destroyed( + ) | rpl::start_with_next([=] { + box->closeBox(); + }, box->lifetime()); + }); + *weak = box.data(); + _show->showBox(std::move(box)); } void ShareBox::Inner::peerUnselected(not_null peer) { @@ -1049,7 +1158,7 @@ void ShareBox::Inner::peerUnselected(not_null peer) { } void ShareBox::Inner::setPeerSelectedChangedCallback( - Fn callback) { + Fn thread, bool selected)> callback) { _peerSelectedChangedCallback = std::move(callback); } @@ -1058,15 +1167,21 @@ void ShareBox::Inner::changePeerCheckState( bool checked, ChangeStateWay useCallback) { chat->checkbox.setChecked(checked); + const auto thread = chatThread(chat); if (checked) { - _selected.insert(chat->peer); + _selected.emplace(thread); setActive(chatIndex(chat->peer)); } else { - _selected.remove(chat->peer); + _selected.remove(thread); + if (chat->topic) { + chat->topicLifetime.destroy(); + chat->topic = nullptr; + updateChatName(chat); + } } if (useCallback != ChangeStateWay::SkipCallback && _peerSelectedChangedCallback) { - _peerSelectedChangedCallback(chat->peer, checked); + _peerSelectedChangedCallback(thread, checked); } } @@ -1122,9 +1237,11 @@ void ShareBox::Inner::peopleReceived( const auto feedList = [&](const QVector &list) { for (const auto &data : list) { if (const auto peer = _descriptor.session->data().peerLoaded( - peerFromMTP(data))) { - const auto history = _descriptor.session->data().historyLoaded(peer); - if (!_descriptor.filterCallback(peer)) { + peerFromMTP(data))) { + const auto history = _descriptor.session->data().history( + peer); + if (!history->asForum() + && !_descriptor.filterCallback(history)) { continue; } else if (history && _chatsIndexed->getRow(history)) { continue; @@ -1136,7 +1253,7 @@ void ShareBox::Inner::peopleReceived( peer, _st.item, [=] { repaintChat(peer); })); - updateChatName(d_byUsernameFiltered.back().get(), peer); + updateChatName(d_byUsernameFiltered.back().get()); } } }; @@ -1158,12 +1275,19 @@ void ShareBox::Inner::refresh() { update(); } -std::vector> ShareBox::Inner::selected() const { - auto result = std::vector>(); +not_null ShareBox::Inner::chatThread( + not_null chat) const { + return chat->topic + ? (Data::Thread*)chat->topic + : chat->peer->owner().history(chat->peer).get(); +} + +std::vector> ShareBox::Inner::selected() const { + auto result = std::vector>(); result.reserve(_dataMap.size()); for (const auto &[peer, chat] : _dataMap) { if (chat->checkbox.checked()) { - result.push_back(peer); + result.push_back(chatThread(chat.get())); } } return result; @@ -1279,7 +1403,7 @@ void FastShareMessage( }; auto submitCallback = [=]( - std::vector> &&result, + std::vector> &&result, TextWithTags &&comment, Api::SendOptions options, Data::ForwardOptions forwardOptions) { @@ -1292,12 +1416,12 @@ void FastShareMessage( } const auto error = [&] { - for (const auto peer : result) { // #TODO forum share + for (const auto thread : result) { const auto error = GetErrorTextForSending( - peer, + thread, { .forward = &items, .text = &comment }); if (!error.isEmpty()) { - return std::make_pair(error, peer); + return std::make_pair(error, thread); } } return std::make_pair(QString(), result.front()); @@ -1306,7 +1430,7 @@ void FastShareMessage( auto text = TextWithEntities(); if (result.size() > 1) { text.append( - Ui::Text::Bold(error.second->name()) + Ui::Text::Bold(error.second->chatListName()) ).append("\n\n"); } text.append(error.first); @@ -1316,17 +1440,16 @@ void FastShareMessage( return; } - const auto commonSendFlags = MTPmessages_ForwardMessages::Flag(0) - | MTPmessages_ForwardMessages::Flag::f_with_my_score - | (options.scheduled - ? MTPmessages_ForwardMessages::Flag::f_schedule_date - : MTPmessages_ForwardMessages::Flag(0)) + using Flag = MTPmessages_ForwardMessages::Flag; + const auto commonSendFlags = Flag(0) + | Flag::f_with_my_score + | (options.scheduled ? Flag::f_schedule_date : Flag(0)) | ((forwardOptions != Data::ForwardOptions::PreserveInfo) - ? MTPmessages_ForwardMessages::Flag::f_drop_author - : MTPmessages_ForwardMessages::Flag(0)) + ? Flag::f_drop_author + : Flag(0)) | ((forwardOptions == Data::ForwardOptions::NoNamesAndCaptions) - ? MTPmessages_ForwardMessages::Flag::f_drop_media_captions - : MTPmessages_ForwardMessages::Flag(0)); + ? Flag::f_drop_media_captions + : Flag(0)); auto msgIds = QVector(); msgIds.reserve(data->msgIds.size()); for (const auto &fullId : data->msgIds) { @@ -1342,21 +1465,23 @@ void FastShareMessage( auto &api = owner->session().api(); auto &histories = owner->histories(); const auto requestType = Data::Histories::RequestType::Send; - for (const auto peer : result) { - const auto history = owner->history(peer); + for (const auto thread : result) { if (!comment.text.isEmpty()) { auto message = Api::MessageToSend( - Api::SendAction(history, options)); + Api::SendAction(thread, options)); message.textWithTags = comment; message.action.clearDraft = false; api.sendMessage(std::move(message)); } + const auto topicRootId = thread->topicRootId(); + const auto peer = thread->peer(); histories.sendRequest(history, requestType, [=](Fn finish) { auto &api = history->session().api(); const auto sendFlags = commonSendFlags + | (topicRootId ? Flag::f_top_msg_id : Flag(0)) | (ShouldSendSilent(peer, options) - ? MTPmessages_ForwardMessages::Flag::f_silent - : MTPmessages_ForwardMessages::Flag(0)); + ? Flag::f_silent + : Flag(0)); history->sendRequestId = api.request( MTPmessages_ForwardMessages( MTP_flags(sendFlags), @@ -1364,7 +1489,7 @@ void FastShareMessage( MTP_vector(msgIds), MTP_vector(generateRandom()), peer->input, - MTPint(), // top_msg_id + MTP_int(topicRootId), MTP_int(options.scheduled), MTP_inputPeerEmpty() // send_as )).done([=](const MTPUpdates &updates, mtpRequestId reqId) { @@ -1397,14 +1522,9 @@ void FastShareMessage( data->requests.insert(history->sendRequestId); } }; - auto filterCallback = [isGame](PeerData *peer) { - if (peer->canWrite()) { // #TODO forum share - if (auto channel = peer->asChannel()) { - return isGame ? (!channel->isBroadcast()) : true; - } - return true; - } - return false; + auto filterCallback = [isGame](not_null thread) { + return thread->canWrite() + && (!isGame || !thread->peer()->isBroadcast()); }; auto copyLinkCallback = canCopyLink ? Fn(std::move(copyCallback)) diff --git a/Telegram/SourceFiles/boxes/share_box.h b/Telegram/SourceFiles/boxes/share_box.h index e9ab80802..5babab6cb 100644 --- a/Telegram/SourceFiles/boxes/share_box.h +++ b/Telegram/SourceFiles/boxes/share_box.h @@ -44,6 +44,7 @@ class IndexedList; namespace Data { enum class ForwardOptions; +class Thread; } // namespace Data namespace Ui { @@ -70,11 +71,11 @@ class ShareBox final : public Ui::BoxContent { public: using CopyCallback = Fn; using SubmitCallback = Fn>&&, + std::vector>&&, TextWithTags&&, Api::SendOptions, Data::ForwardOptions option)>; - using FilterCallback = Fn; + using FilterCallback = Fn)>; struct Descriptor { not_null session; @@ -125,8 +126,8 @@ private: int contentHeight() const; void updateScrollSkips(); - void addPeerToMultiSelect(PeerData *peer, bool skipAnimation = false); - void innerSelectedChanged(PeerData *peer, bool checked); + void addPeerToMultiSelect(not_null thread); + void innerSelectedChanged(not_null thread, bool checked); void peopleDone( const MTPcontacts_Found &result, diff --git a/Telegram/SourceFiles/calls/group/calls_group_settings.cpp b/Telegram/SourceFiles/calls/group/calls_group_settings.cpp index 217ecf3f3..f2f48c4dd 100644 --- a/Telegram/SourceFiles/calls/group/calls_group_settings.cpp +++ b/Telegram/SourceFiles/calls/group/calls_group_settings.cpp @@ -133,7 +133,7 @@ object_ptr ShareInviteLinkBox( showToast(tr::lng_group_invite_copied(tr::now)); }; auto submitCallback = [=]( - std::vector> &&result, + std::vector> &&result, TextWithTags &&comment, Api::SendOptions options, Data::ForwardOptions) { @@ -142,12 +142,12 @@ object_ptr ShareInviteLinkBox( } const auto error = [&] { - for (const auto peer : result) { // #TODO forum share + for (const auto thread : result) { const auto error = GetErrorTextForSending( - peer, + thread, { .text = &comment }); if (!error.isEmpty()) { - return std::make_pair(error, peer); + return std::make_pair(error, thread); } } return std::make_pair(QString(), result.front()); @@ -156,7 +156,7 @@ object_ptr ShareInviteLinkBox( auto text = TextWithEntities(); if (result.size() > 1) { text.append( - Ui::Text::Bold(error.second->name()) + Ui::Text::Bold(error.second->chatListName()) ).append("\n\n"); } text.append(error.first); @@ -182,10 +182,9 @@ object_ptr ShareInviteLinkBox( } const auto owner = &peer->owner(); auto &api = peer->session().api(); - for (const auto peer : result) { - const auto history = owner->history(peer); + for (const auto thread : result) { auto message = Api::MessageToSend( - Api::SendAction(history, options)); + Api::SendAction(thread, options)); message.textWithTags = comment; message.action.clearDraft = false; api.sendMessage(std::move(message)); @@ -195,8 +194,8 @@ object_ptr ShareInviteLinkBox( } showToast(tr::lng_share_done(tr::now)); }; - auto filterCallback = [](PeerData *peer) { - return peer->canWrite(); // #TODO forum share + auto filterCallback = [](not_null thread) { + return thread->canWrite(); // #TODO forum share }; const auto scheduleStyle = [&] { diff --git a/Telegram/SourceFiles/history/history_message.cpp b/Telegram/SourceFiles/history/history_message.cpp index 5ab67cd20..b72b71315 100644 --- a/Telegram/SourceFiles/history/history_message.cpp +++ b/Telegram/SourceFiles/history/history_message.cpp @@ -178,6 +178,13 @@ QString GetErrorTextForSending( return QString(); } +QString GetErrorTextForSending( + not_null thread, + SendingErrorRequest request) { + request.topicRootId = thread->topicRootId(); + return GetErrorTextForSending(thread->peer(), std::move(request)); +} + void RequestDependentMessageData( not_null item, PeerId peerId, diff --git a/Telegram/SourceFiles/history/history_message.h b/Telegram/SourceFiles/history/history_message.h index 80539aa4b..2fd3a2095 100644 --- a/Telegram/SourceFiles/history/history_message.h +++ b/Telegram/SourceFiles/history/history_message.h @@ -15,6 +15,7 @@ struct SendOptions; } // namespace Api namespace Data { +class Thread; struct SponsoredFrom; } // namespace Data @@ -50,6 +51,9 @@ struct SendingErrorRequest { [[nodiscard]] QString GetErrorTextForSending( not_null peer, SendingErrorRequest request); +[[nodiscard]] QString GetErrorTextForSending( + not_null thread, + SendingErrorRequest request); [[nodiscard]] TextWithEntities DropCustomEmoji(TextWithEntities text); diff --git a/Telegram/SourceFiles/history/view/controls/history_view_forward_panel.cpp b/Telegram/SourceFiles/history/view/controls/history_view_forward_panel.cpp index 88c65d624..9d2029bee 100644 --- a/Telegram/SourceFiles/history/view/controls/history_view_forward_panel.cpp +++ b/Telegram/SourceFiles/history/view/controls/history_view_forward_panel.cpp @@ -171,7 +171,7 @@ void ForwardPanel::updateTexts() { }).text; const auto history = item->history(); const auto dropCustomEmoji = !history->session().premium() - && !_to->owningHistory()->peer->isSelf() + && !_to->peer()->isSelf() && (item->computeDropForwardedInfo() || !keepNames); if (dropCustomEmoji) { text = DropCustomEmoji(std::move(text)); diff --git a/Telegram/SourceFiles/history/view/history_view_pinned_section.cpp b/Telegram/SourceFiles/history/view/history_view_pinned_section.cpp index 5a38a3a24..041345d74 100644 --- a/Telegram/SourceFiles/history/view/history_view_pinned_section.cpp +++ b/Telegram/SourceFiles/history/view/history_view_pinned_section.cpp @@ -64,7 +64,7 @@ PinnedMemento::PinnedMemento( : _thread(thread) , _highlightId(highlightId) { _list.setAroundPosition({ - .fullId = FullMsgId(_thread->owningHistory()->peer->id, highlightId), + .fullId = FullMsgId(_thread->peer()->id, highlightId), .date = TimeId(0), }); } @@ -89,7 +89,7 @@ PinnedWidget::PinnedWidget( QWidget *parent, not_null controller, not_null thread) -: Window::SectionWidget(parent, controller, thread->owningHistory()->peer) +: Window::SectionWidget(parent, controller, thread->peer()) , _thread(thread->migrateToOrMe()) , _history(thread->owningHistory()) , _migratedPeer(thread->asHistory() @@ -116,7 +116,7 @@ PinnedWidget::PinnedWidget( Window::ChatThemeValueFromPeer( controller, - thread->owningHistory()->peer + thread->peer() ) | rpl::start_with_next([=](std::shared_ptr &&theme) { _theme = std::move(theme); controller->setChatStyleTheme(_theme); diff --git a/Telegram/SourceFiles/history/view/history_view_pinned_tracker.cpp b/Telegram/SourceFiles/history/view/history_view_pinned_tracker.cpp index f7105a1cd..24abaa03f 100644 --- a/Telegram/SourceFiles/history/view/history_view_pinned_tracker.cpp +++ b/Telegram/SourceFiles/history/view/history_view_pinned_tracker.cpp @@ -79,7 +79,7 @@ void PinnedTracker::refreshViewer() { } _dataLifetime.destroy(); _viewerAroundId = _aroundId; - const auto peer = _thread->owningHistory()->peer; + const auto peer = _thread->peer(); SharedMediaMergedViewer( &peer->session(), SharedMediaMergedKey( diff --git a/Telegram/SourceFiles/inline_bots/bot_attach_web_view.cpp b/Telegram/SourceFiles/inline_bots/bot_attach_web_view.cpp index 233569550..93defc1be 100644 --- a/Telegram/SourceFiles/inline_bots/bot_attach_web_view.cpp +++ b/Telegram/SourceFiles/inline_bots/bot_attach_web_view.cpp @@ -141,7 +141,7 @@ void ShowChooseBox( callback(thread); }; auto filter = [=](not_null thread) -> bool { - const auto peer = thread->owningHistory()->peer; + const auto peer = thread->peer(); if (!thread->canWrite()) { return false; } else if (const auto user = peer->asUser()) { diff --git a/Telegram/SourceFiles/mainwidget.cpp b/Telegram/SourceFiles/mainwidget.cpp index c590bc8b1..da8e343cb 100644 --- a/Telegram/SourceFiles/mainwidget.cpp +++ b/Telegram/SourceFiles/mainwidget.cpp @@ -607,7 +607,7 @@ bool MainWidget::sendPaths(not_null thread) { Ui::show(Ui::MakeInformBox(tr::lng_forward_send_files_cant())); return false; } else if (const auto error = Data::RestrictionError( - thread->owningHistory()->peer, + thread->peer(), ChatRestriction::SendMedia)) { Ui::show(Ui::MakeInformBox(*error)); return false; diff --git a/Telegram/SourceFiles/ui/effects/round_checkbox.cpp b/Telegram/SourceFiles/ui/effects/round_checkbox.cpp index a6098447c..f4d13a65d 100644 --- a/Telegram/SourceFiles/ui/effects/round_checkbox.cpp +++ b/Telegram/SourceFiles/ui/effects/round_checkbox.cpp @@ -10,6 +10,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "ui/rp_widget.h" #include "ui/ui_utility.h" #include "ui/painter.h" +#include "ui/image/image_prepare.h" #include @@ -355,10 +356,15 @@ void RoundCheckbox::prepareInactiveCache() { _inactiveCacheFg = Ui::PixmapFromImage(std::move(cacheFg)); } -RoundImageCheckbox::RoundImageCheckbox(const style::RoundImageCheckbox &st, Fn updateCallback, PaintRoundImage &&paintRoundImage) +RoundImageCheckbox::RoundImageCheckbox( + const style::RoundImageCheckbox &st, + Fn updateCallback, + PaintRoundImage &&paintRoundImage, + Fn roundingRadius) : _st(st) , _updateCallback(updateCallback) , _paintRoundImage(std::move(paintRoundImage)) +, _roundingRadius(std::move(roundingRadius)) , _check(_st.check, _updateCallback) { } @@ -383,6 +389,9 @@ void RoundImageCheckbox::paint(Painter &p, int x, int y, int outerWidth) const { } if (selectionLevel > 0) { + const auto radius = _roundingRadius + ? _roundingRadius() + : ImageRoundRadius::Ellipse; PainterHighQualityEnabler hq(p); p.setOpacity(std::clamp(selectionLevel, 0., 1.)); p.setBrush(Qt::NoBrush); @@ -390,7 +399,18 @@ void RoundImageCheckbox::paint(Painter &p, int x, int y, int outerWidth) const { _fgOverride ? (*_fgOverride) : _st.selectFg->b, _st.selectWidth); p.setPen(pen); - p.drawEllipse(style::rtlrect(x, y, _st.imageRadius * 2, _st.imageRadius * 2, outerWidth)); + const auto rect = style::rtlrect( + x, + y, + _st.imageRadius * 2, + _st.imageRadius * 2, + outerWidth); + if (radius == ImageRoundRadius::Ellipse) { + p.drawEllipse(rect); + } else { + const auto pxRadius = st::roundRadiusLarge; + p.drawRoundedRect(rect, pxRadius, pxRadius); + } p.setOpacity(1.); } if (_st.check.size > 0) { diff --git a/Telegram/SourceFiles/ui/effects/round_checkbox.h b/Telegram/SourceFiles/ui/effects/round_checkbox.h index 2a8926b06..b7a788389 100644 --- a/Telegram/SourceFiles/ui/effects/round_checkbox.h +++ b/Telegram/SourceFiles/ui/effects/round_checkbox.h @@ -11,6 +11,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "styles/style_widgets.h" class Painter; +enum class ImageRoundRadius; namespace Ui { @@ -47,7 +48,11 @@ private: class RoundImageCheckbox { public: using PaintRoundImage = Fn; - RoundImageCheckbox(const style::RoundImageCheckbox &st, Fn updateCallback, PaintRoundImage &&paintRoundImage); + RoundImageCheckbox( + const style::RoundImageCheckbox &st, + Fn updateCallback, + PaintRoundImage &&paintRoundImage, + Fn roundingRadius = nullptr); void paint(Painter &p, int x, int y, int outerWidth) const; float64 checkedAnimationRatio() const; @@ -71,6 +76,7 @@ private: const style::RoundImageCheckbox &_st; Fn _updateCallback; PaintRoundImage _paintRoundImage; + Fn _roundingRadius; QPixmap _wideCache; Ui::Animations::Simple _selection; diff --git a/Telegram/SourceFiles/window/window_peer_menu.cpp b/Telegram/SourceFiles/window/window_peer_menu.cpp index db7880a96..f0c90acce 100644 --- a/Telegram/SourceFiles/window/window_peer_menu.cpp +++ b/Telegram/SourceFiles/window/window_peer_menu.cpp @@ -1290,7 +1290,7 @@ void PeerMenuShareContactBox( // There is no async to make weak from controller. const auto weak = std::make_shared>(); auto callback = [=](not_null thread) { - const auto peer = thread->owningHistory()->peer; + const auto peer = thread->peer(); if (!thread->canWrite()) { navigation->parentController()->show( Ui::MakeInformBox(tr::lng_forward_share_cant()), @@ -1544,7 +1544,7 @@ QPointer ShowForwardMessagesBox( weak, navigation ](not_null thread) mutable { - const auto peer = thread->owningHistory()->peer; + const auto peer = thread->peer(); const auto content = navigation->parentController()->content(); if (peer->isSelf() && !draft.ids.empty() @@ -1604,7 +1604,7 @@ QPointer ShowShareGameBox( ShowAtUnreadMsgId, SectionShow::Way::ClearStack); }); - const auto confirmText = thread->owningHistory()->peer->isUser() + const auto confirmText = thread->peer()->isUser() ? tr::lng_bot_sure_share_game( tr::now, lt_user, @@ -1621,7 +1621,7 @@ QPointer ShowShareGameBox( Ui::LayerOption::KeepOther); }; auto filter = [](not_null thread) { - const auto peer = thread->owningHistory()->peer; + const auto peer = thread->peer(); return (thread->canWrite() || thread->asForum()) && !peer->amRestricted(ChatRestriction::SendGames) && !peer->isSelf();