From ea10cf5758c160423c820d010e451c6ae1496bff Mon Sep 17 00:00:00 2001 From: 23rd <23rd@vivaldi.net> Date: Wed, 20 Oct 2021 22:56:10 +0300 Subject: [PATCH] Moved api polls processing to separated file. --- Telegram/CMakeLists.txt | 2 + Telegram/SourceFiles/api/api_polls.cpp | 201 ++++++++++++++++++ Telegram/SourceFiles/api/api_polls.h | 49 +++++ Telegram/SourceFiles/apiwrap.cpp | 170 +-------------- Telegram/SourceFiles/apiwrap.h | 18 +- Telegram/SourceFiles/data/data_poll.cpp | 11 +- Telegram/SourceFiles/data/data_poll.h | 2 +- .../view/history_view_context_menu.cpp | 5 +- .../history/view/media/history_view_poll.cpp | 9 +- .../SourceFiles/window/window_peer_menu.cpp | 3 +- 10 files changed, 276 insertions(+), 194 deletions(-) create mode 100644 Telegram/SourceFiles/api/api_polls.cpp create mode 100644 Telegram/SourceFiles/api/api_polls.h diff --git a/Telegram/CMakeLists.txt b/Telegram/CMakeLists.txt index eca2f354f..5ce76bd32 100644 --- a/Telegram/CMakeLists.txt +++ b/Telegram/CMakeLists.txt @@ -128,6 +128,8 @@ PRIVATE api/api_media.h api/api_peer_photo.cpp api/api_peer_photo.h + api/api_polls.cpp + api/api_polls.h api/api_self_destruct.cpp api/api_self_destruct.h api/api_send_progress.cpp diff --git a/Telegram/SourceFiles/api/api_polls.cpp b/Telegram/SourceFiles/api/api_polls.cpp new file mode 100644 index 000000000..1113cf655 --- /dev/null +++ b/Telegram/SourceFiles/api/api_polls.cpp @@ -0,0 +1,201 @@ +/* +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 "api/api_polls.h" + +#include "api/api_common.h" +#include "api/api_updates.h" +#include "apiwrap.h" +#include "base/random.h" +#include "data/data_changes.h" +#include "data/data_histories.h" +#include "data/data_poll.h" +#include "data/data_session.h" +#include "history/history.h" +#include "history/history_message.h" // ShouldSendSilent +#include "main/main_session.h" + +namespace Api { +namespace { + +[[nodiscard]] TimeId UnixtimeFromMsgId(mtpMsgId msgId) { + return TimeId(msgId >> 32); +} + +} // namespace + +Polls::Polls(not_null api) +: _session(&api->session()) +, _api(&api->instance()) { +} + +void Polls::create( + const PollData &data, + const SendAction &action, + Fn done, + Fn fail) { + _session->api().sendAction(action); + + const auto history = action.history; + const auto peer = history->peer; + auto sendFlags = MTPmessages_SendMedia::Flags(0); + if (action.replyTo) { + sendFlags |= MTPmessages_SendMedia::Flag::f_reply_to_msg_id; + } + const auto clearCloudDraft = action.clearDraft; + if (clearCloudDraft) { + sendFlags |= MTPmessages_SendMedia::Flag::f_clear_draft; + history->clearLocalDraft(); + history->clearCloudDraft(); + history->startSavingCloudDraft(); + } + const auto silentPost = ShouldSendSilent(peer, action.options); + if (silentPost) { + sendFlags |= MTPmessages_SendMedia::Flag::f_silent; + } + if (action.options.scheduled) { + sendFlags |= MTPmessages_SendMedia::Flag::f_schedule_date; + } + auto &histories = history->owner().histories(); + const auto requestType = Data::Histories::RequestType::Send; + histories.sendRequest(history, requestType, [=](Fn finish) { + const auto replyTo = action.replyTo; + history->sendRequestId = _api.request(MTPmessages_SendMedia( + MTP_flags(sendFlags), + peer->input, + MTP_int(replyTo), + PollDataToInputMedia(&data), + MTP_string(), + MTP_long(base::RandomValue()), + MTPReplyMarkup(), + MTPVector(), + MTP_int(action.options.scheduled) + )).done([=]( + const MTPUpdates &result, + const MTP::Response &response) mutable { + _session->updates().applyUpdates(result); + if (clearCloudDraft) { + history->finishSavingCloudDraft( + UnixtimeFromMsgId(response.outerMsgId)); + } + _session->changes().historyUpdated( + history, + (action.options.scheduled + ? Data::HistoryUpdate::Flag::ScheduledSent + : Data::HistoryUpdate::Flag::MessageSent)); + done(); + finish(); + }).fail([=]( + const MTP::Error &error, + const MTP::Response &response) mutable { + if (clearCloudDraft) { + history->finishSavingCloudDraft( + UnixtimeFromMsgId(response.outerMsgId)); + } + fail(error); + finish(); + }).afterRequest(history->sendRequestId + ).send(); + return history->sendRequestId; + }); +} + +void Polls::sendVotes( + FullMsgId itemId, + const std::vector &options) { + if (_pollVotesRequestIds.contains(itemId)) { + return; + } + const auto item = _session->data().message(itemId); + const auto media = item ? item->media() : nullptr; + const auto poll = media ? media->poll() : nullptr; + if (!item) { + return; + } + + const auto showSending = poll && !options.empty(); + const auto hideSending = [=] { + if (showSending) { + if (const auto item = _session->data().message(itemId)) { + poll->sendingVotes.clear(); + _session->data().requestItemRepaint(item); + } + } + }; + if (showSending) { + poll->sendingVotes = options; + _session->data().requestItemRepaint(item); + } + + auto prepared = QVector(); + prepared.reserve(options.size()); + ranges::transform( + options, + ranges::back_inserter(prepared), + [](const QByteArray &option) { return MTP_bytes(option); }); + const auto requestId = _api.request(MTPmessages_SendVote( + item->history()->peer->input, + MTP_int(item->id), + MTP_vector(prepared) + )).done([=](const MTPUpdates &result) { + _pollVotesRequestIds.erase(itemId); + hideSending(); + _session->updates().applyUpdates(result); + }).fail([=](const MTP::Error &error) { + _pollVotesRequestIds.erase(itemId); + hideSending(); + }).send(); + _pollVotesRequestIds.emplace(itemId, requestId); +} + +void Polls::close(not_null item) { + const auto itemId = item->fullId(); + if (_pollCloseRequestIds.contains(itemId)) { + return; + } + const auto media = item ? item->media() : nullptr; + const auto poll = media ? media->poll() : nullptr; + if (!poll) { + return; + } + const auto requestId = _api.request(MTPmessages_EditMessage( + MTP_flags(MTPmessages_EditMessage::Flag::f_media), + item->history()->peer->input, + MTP_int(item->id), + MTPstring(), + PollDataToInputMedia(poll, true), + MTPReplyMarkup(), + MTPVector(), + MTP_int(0) // schedule_date + )).done([=](const MTPUpdates &result) { + _pollCloseRequestIds.erase(itemId); + _session->updates().applyUpdates(result); + }).fail([=](const MTP::Error &error) { + _pollCloseRequestIds.erase(itemId); + }).send(); + _pollCloseRequestIds.emplace(itemId, requestId); +} + +void Polls::reloadResults(not_null item) { + const auto itemId = item->fullId(); + if (!IsServerMsgId(item->id) + || _pollReloadRequestIds.contains(itemId)) { + return; + } + const auto requestId = _api.request(MTPmessages_GetPollResults( + item->history()->peer->input, + MTP_int(item->id) + )).done([=](const MTPUpdates &result) { + _pollReloadRequestIds.erase(itemId); + _session->updates().applyUpdates(result); + }).fail([=](const MTP::Error &error) { + _pollReloadRequestIds.erase(itemId); + }).send(); + _pollReloadRequestIds.emplace(itemId, requestId); +} + +} // namespace Api diff --git a/Telegram/SourceFiles/api/api_polls.h b/Telegram/SourceFiles/api/api_polls.h new file mode 100644 index 000000000..29ffe3142 --- /dev/null +++ b/Telegram/SourceFiles/api/api_polls.h @@ -0,0 +1,49 @@ +/* +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 + +#include "mtproto/sender.h" + +class ApiWrap; +class HistoryItem; +struct PollData; + +namespace Main { +class Session; +} // namespace Main + +namespace Api { + +struct SendAction; + +class Polls final { +public: + explicit Polls(not_null api); + + void create( + const PollData &data, + const SendAction &action, + Fn done, + Fn fail); + void sendVotes( + FullMsgId itemId, + const std::vector &options); + void close(not_null item); + void reloadResults(not_null item); + +private: + const not_null _session; + MTP::Sender _api; + + base::flat_map _pollVotesRequestIds; + base::flat_map _pollCloseRequestIds; + base::flat_map _pollReloadRequestIds; + +}; + +} // namespace Api diff --git a/Telegram/SourceFiles/apiwrap.cpp b/Telegram/SourceFiles/apiwrap.cpp index 8afff3477..3fa3c45d4 100644 --- a/Telegram/SourceFiles/apiwrap.cpp +++ b/Telegram/SourceFiles/apiwrap.cpp @@ -15,6 +15,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "api/api_invite_links.h" #include "api/api_media.h" #include "api/api_peer_photo.h" +#include "api/api_polls.h" #include "api/api_sending.h" #include "api/api_text_entities.h" #include "api/api_self_destruct.h" @@ -29,7 +30,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "data/data_changes.h" #include "data/data_photo.h" #include "data/data_web_page.h" -#include "data/data_poll.h" #include "data/data_folder.h" #include "data/data_media_types.h" #include "data/data_sparse_ids.h" @@ -147,7 +147,8 @@ ApiWrap::ApiWrap(not_null session) , _inviteLinks(std::make_unique(this)) , _views(std::make_unique(this)) , _confirmPhone(std::make_unique(this)) -, _peerPhoto(std::make_unique(this)) { +, _peerPhoto(std::make_unique(this)) +, _polls(std::make_unique(this)) { crl::on_main(session, [=] { // You can't use _session->lifetime() in the constructor, // only queued, because it is not constructed yet. @@ -4612,167 +4613,6 @@ Api::PeerPhoto &ApiWrap::peerPhoto() { return *_peerPhoto; } -void ApiWrap::createPoll( - const PollData &data, - const SendAction &action, - Fn done, - Fn fail) { - sendAction(action); - - const auto history = action.history; - const auto peer = history->peer; - auto sendFlags = MTPmessages_SendMedia::Flags(0); - if (action.replyTo) { - sendFlags |= MTPmessages_SendMedia::Flag::f_reply_to_msg_id; - } - const auto clearCloudDraft = action.clearDraft; - if (clearCloudDraft) { - sendFlags |= MTPmessages_SendMedia::Flag::f_clear_draft; - history->clearLocalDraft(); - history->clearCloudDraft(); - history->startSavingCloudDraft(); - } - const auto silentPost = ShouldSendSilent(peer, action.options); - if (silentPost) { - sendFlags |= MTPmessages_SendMedia::Flag::f_silent; - } - if (action.options.scheduled) { - sendFlags |= MTPmessages_SendMedia::Flag::f_schedule_date; - } - auto &histories = history->owner().histories(); - const auto requestType = Data::Histories::RequestType::Send; - histories.sendRequest(history, requestType, [=](Fn finish) { - const auto replyTo = action.replyTo; - history->sendRequestId = request(MTPmessages_SendMedia( - MTP_flags(sendFlags), - peer->input, - MTP_int(replyTo), - PollDataToInputMedia(&data), - MTP_string(), - MTP_long(base::RandomValue()), - MTPReplyMarkup(), - MTPVector(), - MTP_int(action.options.scheduled) - )).done([=]( - const MTPUpdates &result, - const MTP::Response &response) mutable { - applyUpdates(result); - if (clearCloudDraft) { - history->finishSavingCloudDraft( - UnixtimeFromMsgId(response.outerMsgId)); - } - _session->changes().historyUpdated( - history, - (action.options.scheduled - ? Data::HistoryUpdate::Flag::ScheduledSent - : Data::HistoryUpdate::Flag::MessageSent)); - done(); - finish(); - }).fail([=]( - const MTP::Error &error, - const MTP::Response &response) mutable { - if (clearCloudDraft) { - history->finishSavingCloudDraft( - UnixtimeFromMsgId(response.outerMsgId)); - } - fail(error); - finish(); - }).afterRequest(history->sendRequestId - ).send(); - return history->sendRequestId; - }); -} - -void ApiWrap::sendPollVotes( - FullMsgId itemId, - const std::vector &options) { - if (_pollVotesRequestIds.contains(itemId)) { - return; - } - const auto item = _session->data().message(itemId); - const auto media = item ? item->media() : nullptr; - const auto poll = media ? media->poll() : nullptr; - if (!item) { - return; - } - - const auto showSending = poll && !options.empty(); - const auto hideSending = [=] { - if (showSending) { - if (const auto item = _session->data().message(itemId)) { - poll->sendingVotes.clear(); - _session->data().requestItemRepaint(item); - } - } - }; - if (showSending) { - poll->sendingVotes = options; - _session->data().requestItemRepaint(item); - } - - auto prepared = QVector(); - prepared.reserve(options.size()); - ranges::transform( - options, - ranges::back_inserter(prepared), - [](const QByteArray &option) { return MTP_bytes(option); }); - const auto requestId = request(MTPmessages_SendVote( - item->history()->peer->input, - MTP_int(item->id), - MTP_vector(prepared) - )).done([=](const MTPUpdates &result) { - _pollVotesRequestIds.erase(itemId); - hideSending(); - applyUpdates(result); - }).fail([=](const MTP::Error &error) { - _pollVotesRequestIds.erase(itemId); - hideSending(); - }).send(); - _pollVotesRequestIds.emplace(itemId, requestId); -} - -void ApiWrap::closePoll(not_null item) { - const auto itemId = item->fullId(); - if (_pollCloseRequestIds.contains(itemId)) { - return; - } - const auto media = item ? item->media() : nullptr; - const auto poll = media ? media->poll() : nullptr; - if (!poll) { - return; - } - const auto requestId = request(MTPmessages_EditMessage( - MTP_flags(MTPmessages_EditMessage::Flag::f_media), - item->history()->peer->input, - MTP_int(item->id), - MTPstring(), - PollDataToInputMedia(poll, true), - MTPReplyMarkup(), - MTPVector(), - MTP_int(0) // schedule_date - )).done([=](const MTPUpdates &result) { - _pollCloseRequestIds.erase(itemId); - applyUpdates(result); - }).fail([=](const MTP::Error &error) { - _pollCloseRequestIds.erase(itemId); - }).send(); - _pollCloseRequestIds.emplace(itemId, requestId); -} - -void ApiWrap::reloadPollResults(not_null item) { - const auto itemId = item->fullId(); - if (!IsServerMsgId(item->id) - || _pollReloadRequestIds.contains(itemId)) { - return; - } - const auto requestId = request(MTPmessages_GetPollResults( - item->history()->peer->input, - MTP_int(item->id) - )).done([=](const MTPUpdates &result) { - _pollReloadRequestIds.erase(itemId); - applyUpdates(result); - }).fail([=](const MTP::Error &error) { - _pollReloadRequestIds.erase(itemId); - }).send(); - _pollReloadRequestIds.emplace(itemId, requestId); +Api::Polls &ApiWrap::polls() { + return *_polls; } diff --git a/Telegram/SourceFiles/apiwrap.h b/Telegram/SourceFiles/apiwrap.h index 0031cbdc9..ce7fea195 100644 --- a/Telegram/SourceFiles/apiwrap.h +++ b/Telegram/SourceFiles/apiwrap.h @@ -65,6 +65,7 @@ class InviteLinks; class ViewsManager; class ConfirmPhone; class PeerPhoto; +class Polls; namespace details { @@ -403,17 +404,7 @@ public: [[nodiscard]] Api::ViewsManager &views(); [[nodiscard]] Api::ConfirmPhone &confirmPhone(); [[nodiscard]] Api::PeerPhoto &peerPhoto(); - - void createPoll( - const PollData &data, - const SendAction &action, - Fn done, - Fn fail); - void sendPollVotes( - FullMsgId itemId, - const std::vector &options); - void closePoll(not_null item); - void reloadPollResults(not_null item); + [[nodiscard]] Api::Polls &polls(); void updatePrivacyLastSeens(); @@ -722,10 +713,7 @@ private: const std::unique_ptr _views; const std::unique_ptr _confirmPhone; const std::unique_ptr _peerPhoto; - - base::flat_map _pollVotesRequestIds; - base::flat_map _pollCloseRequestIds; - base::flat_map _pollReloadRequestIds; + const std::unique_ptr _polls; mtpRequestId _wallPaperRequestId = 0; QString _wallPaperSlug; diff --git a/Telegram/SourceFiles/data/data_poll.cpp b/Telegram/SourceFiles/data/data_poll.cpp index 3d0e7fa04..ce2cbee35 100644 --- a/Telegram/SourceFiles/data/data_poll.cpp +++ b/Telegram/SourceFiles/data/data_poll.cpp @@ -7,7 +7,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL */ #include "data/data_poll.h" -#include "apiwrap.h" #include "data/data_user.h" #include "data/data_session.h" #include "base/call_delayed.h" @@ -177,17 +176,15 @@ bool PollData::applyResults(const MTPPollResults &results) { }); } -void PollData::checkResultsReload( - not_null item, - crl::time now) { +bool PollData::checkResultsReload(crl::time now) { if (_lastResultsUpdate > 0 && _lastResultsUpdate + kShortPollTimeout > now) { - return; + return false; } else if (closed() && _lastResultsUpdate >= 0) { - return; + return false; } _lastResultsUpdate = now; - _owner->session().api().reloadPollResults(item); + return true; } PollAnswer *PollData::answerByOption(const QByteArray &option) { diff --git a/Telegram/SourceFiles/data/data_poll.h b/Telegram/SourceFiles/data/data_poll.h index 9a0229983..72d2731d6 100644 --- a/Telegram/SourceFiles/data/data_poll.h +++ b/Telegram/SourceFiles/data/data_poll.h @@ -50,7 +50,7 @@ struct PollData { bool closeByTimer(); bool applyChanges(const MTPDpoll &poll); bool applyResults(const MTPPollResults &results); - void checkResultsReload(not_null item, crl::time now); + [[nodiscard]] bool checkResultsReload(crl::time now); [[nodiscard]] PollAnswer *answerByOption(const QByteArray &option); [[nodiscard]] const PollAnswer *answerByOption( diff --git a/Telegram/SourceFiles/history/view/history_view_context_menu.cpp b/Telegram/SourceFiles/history/view/history_view_context_menu.cpp index b3d5b115e..399de7ba8 100644 --- a/Telegram/SourceFiles/history/view/history_view_context_menu.cpp +++ b/Telegram/SourceFiles/history/view/history_view_context_menu.cpp @@ -9,6 +9,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "api/api_attached_stickers.h" #include "api/api_editing.h" +#include "api/api_polls.h" #include "api/api_toggling_media.h" // Api::ToggleFavedSticker #include "base/unixtime.h" #include "history/view/history_view_list_widget.h" @@ -1007,7 +1008,7 @@ void StopPoll(not_null session, FullMsgId itemId) { const auto stop = [=] { Ui::hideLayer(); if (const auto item = session->data().message(itemId)) { - session->api().closePoll(item); + session->api().polls().close(item); } }; Ui::show(Box( @@ -1033,7 +1034,7 @@ void AddPollActions( const auto itemId = item->fullId(); if (poll->voted() && !poll->quiz()) { menu->addAction(tr::lng_polls_retract(tr::now), [=] { - poll->session().api().sendPollVotes(itemId, {}); + poll->session().api().polls().sendVotes(itemId, {}); }); } if (item->canStopPoll()) { diff --git a/Telegram/SourceFiles/history/view/media/history_view_poll.cpp b/Telegram/SourceFiles/history/view/media/history_view_poll.cpp index 917416b13..e6e35c9cf 100644 --- a/Telegram/SourceFiles/history/view/media/history_view_poll.cpp +++ b/Telegram/SourceFiles/history/view/media/history_view_poll.cpp @@ -31,6 +31,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "base/timer.h" #include "main/main_session.h" #include "apiwrap.h" +#include "api/api_polls.h" #include "styles/style_chat.h" #include "styles/style_widgets.h" #include "styles/style_window.h" @@ -546,7 +547,7 @@ ClickHandlerPtr Poll::createAnswerClickHandler( } return std::make_shared(crl::guard(this, [=] { _votedFromHere = true; - history()->session().api().sendPollVotes( + history()->session().api().polls().sendVotes( _parent->data()->fullId(), { option }); })); @@ -586,7 +587,7 @@ void Poll::sendMultiOptions() { ) | ranges::to_vector; if (!chosen.empty()) { _votedFromHere = true; - history()->session().api().sendPollVotes( + history()->session().api().polls().sendVotes( _parent->data()->fullId(), std::move(chosen)); } @@ -721,7 +722,9 @@ void Poll::draw(Painter &p, const PaintContext &context) const { auto paintw = width(); checkSendingAnimation(); - _poll->checkResultsReload(_parent->data(), context.now); + if (_poll->checkResultsReload(context.now)) { + history()->session().api().polls().reloadResults(_parent->data()); + } const auto stm = context.messageStyle(); const auto padding = st::msgPadding; diff --git a/Telegram/SourceFiles/window/window_peer_menu.cpp b/Telegram/SourceFiles/window/window_peer_menu.cpp index c6f5cac66..e98e8b4fe 100644 --- a/Telegram/SourceFiles/window/window_peer_menu.cpp +++ b/Telegram/SourceFiles/window/window_peer_menu.cpp @@ -31,6 +31,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "mainwindow.h" #include "api/api_blocked_peers.h" #include "api/api_chat_filters.h" +#include "api/api_polls.h" #include "api/api_updates.h" #include "mtproto/mtproto_config.h" #include "history/history.h" @@ -828,7 +829,7 @@ void PeerMenuCreatePoll( action.clearDraft = localDraft->textWithTags.text.isEmpty(); } const auto api = &peer->session().api(); - api->createPoll(result.poll, action, crl::guard(box, [=] { + api->polls().create(result.poll, action, crl::guard(box, [=] { box->closeBox(); }), crl::guard(box, [=](const MTP::Error &error) { *lock = false;