diff --git a/Telegram/CMakeLists.txt b/Telegram/CMakeLists.txt index 5608edf262..060290eceb 100644 --- a/Telegram/CMakeLists.txt +++ b/Telegram/CMakeLists.txt @@ -1230,6 +1230,8 @@ PRIVATE lang/lang_numbers_animation.h lang/lang_translator.cpp lang/lang_translator.h + lang/translate_provider.cpp + lang/translate_provider.h layout/layout_document_generic_preview.cpp layout/layout_document_generic_preview.h layout/layout_item_base.cpp diff --git a/Telegram/SourceFiles/boxes/translate_box.cpp b/Telegram/SourceFiles/boxes/translate_box.cpp index ed103018d6..d07a87f74a 100644 --- a/Telegram/SourceFiles/boxes/translate_box.cpp +++ b/Telegram/SourceFiles/boxes/translate_box.cpp @@ -7,8 +7,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL */ #include "boxes/translate_box.h" #include "boxes/translate_box_content.h" +#include "lang/translate_provider.h" -#include "api/api_text_entities.h" // Api::EntitiesToMTP / EntitiesFromMTP. #include "core/application.h" #include "core/core_settings.h" #include "core/ui_integration.h" @@ -18,7 +18,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "lang/lang_instance.h" #include "lang/lang_keys.h" #include "main/main_session.h" -#include "mtproto/sender.h" #include "spellcheck/platform/platform_language.h" #include "ui/boxes/choose_language_box.h" #include "ui/layers/generic_box.h" @@ -39,29 +38,24 @@ void TranslateBox( TextWithEntities text, bool hasCopyRestriction) { struct State { - State(not_null session) : api(&session->mtp()) { + State(not_null session) + : provider(CreateTranslateProvider(session)) { } - MTP::Sender api; + std::unique_ptr provider; rpl::variable to; }; const auto state = box->lifetime().make_state(&peer->session()); state->to = ChooseTranslateTo(peer->owner().history(peer)); - - if (!IsServerMsgId(msgId)) { - msgId = 0; - } - - using Flag = MTPmessages_TranslateText::Flag; - const auto flags = msgId - ? (Flag::f_peer | Flag::f_id) - : !text.text.isEmpty() - ? Flag::f_text - : Flag(0); - const auto requestText = text; + const auto request = std::make_shared( + PrepareTranslateProviderRequest( + state->provider.get(), + peer, + msgId, + std::move(text))); TranslateBoxContent(box, { - .text = std::move(text), + .text = request->text, .hasCopyRestriction = hasCopyRestriction, .textContext = Core::TextContext({ .session = &peer->session() }), .to = state->to.value(), @@ -71,33 +65,7 @@ void TranslateBox( crl::guard(box, [=](LanguageId id) { state->to = id; }))); }, .request = [=](LanguageId to, Fn)> done) { - const auto callback = std::make_shared< - Fn)>>(std::move(done)); - state->api.request(MTPmessages_TranslateText( - MTP_flags(flags), - msgId ? peer->input() : MTP_inputPeerEmpty(), - (msgId - ? MTP_vector(1, MTP_int(msgId)) - : MTPVector()), - (msgId - ? MTPVector() - : MTP_vector(1, MTP_textWithEntities( - MTP_string(requestText.text), - Api::EntitiesToMTP( - &peer->session(), - requestText.entities, - Api::ConvertOption::SkipLocal)))), - MTP_string(to.twoLetterCode()) - )).done([=](const MTPmessages_TranslatedText &result) { - const auto &data = result.data(); - const auto &list = data.vresult().v; - (*callback)(list.isEmpty() - ? std::optional() - : std::optional( - Api::ParseTextWithEntities(&peer->session(), list.front()))); - }).fail([=](const MTP::Error &) { - (*callback)(std::nullopt); - }).send(); + state->provider->request(*request, to, std::move(done)); }, }); } diff --git a/Telegram/SourceFiles/lang/translate_provider.cpp b/Telegram/SourceFiles/lang/translate_provider.cpp new file mode 100644 index 0000000000..e56ea74184 --- /dev/null +++ b/Telegram/SourceFiles/lang/translate_provider.cpp @@ -0,0 +1,121 @@ +/* +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 "lang/translate_provider.h" + +#include "api/api_text_entities.h" +#include "data/data_msg_id.h" +#include "data/data_peer.h" +#include "data/data_session.h" +#include "history/history_item.h" +#include "main/main_session.h" +#include "mtproto/sender.h" + +namespace Ui { +namespace { + +enum class TranslateProviderKind { + MTProtoServer, +}; + +[[nodiscard]] TranslateProviderKind CurrentTranslateProviderKind() { + return TranslateProviderKind::MTProtoServer; +} + +class MTProtoTranslateProvider final : public TranslateProvider { +public: + explicit MTProtoTranslateProvider(not_null session) + : _api(&session->mtp()) { + } + + [[nodiscard]] bool supportsMessageId() const override { + return true; + } + + void request( + TranslateProviderRequest request, + LanguageId to, + Fn)> done) override { + using Flag = MTPmessages_TranslateText::Flag; + const auto flags = request.msgId + ? (Flag::f_peer | Flag::f_id) + : !request.text.text.isEmpty() + ? Flag::f_text + : Flag(0); + if (!flags) { + done(std::nullopt); + return; + } + const auto callback = std::make_shared< + Fn)>>(std::move(done)); + _api.request(MTPmessages_TranslateText( + MTP_flags(flags), + request.msgId ? request.peer->input() : MTP_inputPeerEmpty(), + (request.msgId + ? MTP_vector(1, MTP_int(request.msgId)) + : MTPVector()), + (request.msgId + ? MTPVector() + : MTP_vector(1, MTP_textWithEntities( + MTP_string(request.text.text), + Api::EntitiesToMTP( + &request.peer->session(), + request.text.entities, + Api::ConvertOption::SkipLocal)))), + MTP_string(to.twoLetterCode()) + )).done([=](const MTPmessages_TranslatedText &result) { + const auto &data = result.data(); + const auto &list = data.vresult().v; + (*callback)(list.isEmpty() + ? std::optional() + : std::optional(Api::ParseTextWithEntities( + &request.peer->session(), + list.front()))); + }).fail([=](const MTP::Error &) { + (*callback)(std::nullopt); + }).send(); + } + +private: + MTP::Sender _api; + +}; + +} // namespace + +std::unique_ptr CreateTranslateProvider( + not_null session) { + switch (CurrentTranslateProviderKind()) { + case TranslateProviderKind::MTProtoServer: + return std::make_unique(session); + } + return std::make_unique(session); +} + +TranslateProviderRequest PrepareTranslateProviderRequest( + not_null provider, + not_null peer, + MsgId msgId, + TextWithEntities text) { + auto result = TranslateProviderRequest{ + .peer = peer, + .msgId = IsServerMsgId(msgId) ? msgId : MsgId(), + .text = std::move(text), + }; + if (provider->supportsMessageId()) { + return result; + } + if (result.msgId) { + if (const auto item = peer->owner().message(peer, result.msgId)) { + result.text = item->originalText(); + } + result.msgId = 0; + } + return result; +} + +} // namespace Ui diff --git a/Telegram/SourceFiles/lang/translate_provider.h b/Telegram/SourceFiles/lang/translate_provider.h new file mode 100644 index 0000000000..8da0ca0950 --- /dev/null +++ b/Telegram/SourceFiles/lang/translate_provider.h @@ -0,0 +1,46 @@ +/* +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 "spellcheck/platform/platform_language.h" +#include "ui/text/text_entity.h" + +class PeerData; + +namespace Main { +class Session; +} // namespace Main + +namespace Ui { + +struct TranslateProviderRequest { + not_null peer; + MsgId msgId = 0; + TextWithEntities text; +}; + +class TranslateProvider { +public: + virtual ~TranslateProvider() = default; + [[nodiscard]] virtual bool supportsMessageId() const = 0; + virtual void request( + TranslateProviderRequest request, + LanguageId to, + Fn)> done) = 0; +}; + +[[nodiscard]] std::unique_ptr CreateTranslateProvider( + not_null session); + +[[nodiscard]] TranslateProviderRequest PrepareTranslateProviderRequest( + not_null provider, + not_null peer, + MsgId msgId, + TextWithEntities text); + +} // namespace Ui