diff --git a/Telegram/CMakeLists.txt b/Telegram/CMakeLists.txt index d900b1f875..9614a44782 100644 --- a/Telegram/CMakeLists.txt +++ b/Telegram/CMakeLists.txt @@ -287,6 +287,8 @@ PRIVATE boxes/sticker_set_box.h boxes/stickers_box.cpp boxes/stickers_box.h + boxes/translate_box.cpp + boxes/translate_box.h boxes/url_auth_box.cpp boxes/url_auth_box.h boxes/username_box.cpp diff --git a/Telegram/Resources/langs/lang.strings b/Telegram/Resources/langs/lang.strings index 221425e2ec..19de99a52d 100644 --- a/Telegram/Resources/langs/lang.strings +++ b/Telegram/Resources/langs/lang.strings @@ -3385,6 +3385,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL "lng_language_not_ready_about" = "Unfortunately, this custom language pack ({lang_name}) doesn't contain data for Telegram Desktop. You can contribute to this language pack using the {link}."; "lng_language_not_ready_link" = "translations platform"; +"lng_translate_box_original" = "Original"; +"lng_translate_box_error" = "Translate failed."; + "lng_launch_exe_warning" = "This file has a {extension} extension.\nAre you sure you want to run it?"; "lng_launch_svg_warning" = "Opening this file can potentially expose your IP address to its sender. Continue?"; "lng_launch_exe_sure" = "Run"; diff --git a/Telegram/SourceFiles/boxes/about_sponsored_box.cpp b/Telegram/SourceFiles/boxes/about_sponsored_box.cpp index b64500de6d..866f98ec27 100644 --- a/Telegram/SourceFiles/boxes/about_sponsored_box.cpp +++ b/Telegram/SourceFiles/boxes/about_sponsored_box.cpp @@ -8,6 +8,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "boxes/about_sponsored_box.h" #include "lang/lang_keys.h" +#include "ui/layers/generic_box.h" #include "ui/widgets/buttons.h" #include "ui/widgets/labels.h" #include "styles/style_boxes.h" diff --git a/Telegram/SourceFiles/boxes/about_sponsored_box.h b/Telegram/SourceFiles/boxes/about_sponsored_box.h index b6686b0ce2..bcd1220968 100644 --- a/Telegram/SourceFiles/boxes/about_sponsored_box.h +++ b/Telegram/SourceFiles/boxes/about_sponsored_box.h @@ -7,10 +7,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL */ #pragma once -#include "ui/layers/generic_box.h" - namespace Ui { +class GenericBox; + void AboutSponsoredBox(not_null box); } // namespace Ui diff --git a/Telegram/SourceFiles/boxes/translate_box.cpp b/Telegram/SourceFiles/boxes/translate_box.cpp new file mode 100644 index 0000000000..ef63db2d51 --- /dev/null +++ b/Telegram/SourceFiles/boxes/translate_box.cpp @@ -0,0 +1,174 @@ +/* +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 "boxes/translate_box.h" + +#include "data/data_peer.h" +#include "lang/lang_instance.h" +#include "lang/lang_keys.h" +#include "main/main_session.h" +#include "mtproto/sender.h" +#include "settings/settings_common.h" +#include "ui/layers/generic_box.h" +#include "ui/widgets/buttons.h" +#include "ui/widgets/labels.h" +#include "ui/wrap/fade_wrap.h" +#include "ui/wrap/slide_wrap.h" +#include "styles/style_boxes.h" +#include "styles/style_chat_helpers.h" +#include "styles/style_layers.h" + +namespace Ui { +namespace { + +class ShowButton : public RpWidget { +public: + ShowButton(not_null parent); + + [[nodiscard]] rpl::producer clicks() const; + +protected: + void paintEvent(QPaintEvent *e) override; + +private: + LinkButton _button; + +}; + +ShowButton::ShowButton(not_null parent) +: RpWidget(parent) +, _button(this, tr::lng_usernames_activate_confirm(tr::now)) { + _button.sizeValue( + ) | rpl::start_with_next([=](const QSize &s) { + resize( + s.width() + st::emojiSuggestionsFadeRight.width(), + s.height()); + _button.moveToRight(0, 0); + }, lifetime()); + _button.show(); +} + +void ShowButton::paintEvent(QPaintEvent *e) { + auto p = QPainter(this); + const auto clip = e->rect(); + + const auto &icon = st::emojiSuggestionsFadeRight; + const auto fade = QRect(0, 0, icon.width(), height()); + if (fade.intersects(clip)) { + icon.fill(p, fade); + } + const auto fill = clip.intersected( + { icon.width(), 0, width() - icon.width(), height() }); + if (!fill.isEmpty()) { + p.fillRect(fill, st::boxBg); + } +} + +rpl::producer ShowButton::clicks() const { + return _button.clicks(); +} + +} // namespace + +void TranslateBox( + not_null box, + not_null peer, + MsgId msgId, + TextWithEntities text) { + box->setWidth(st::boxWideWidth); + box->addButton(tr::lng_box_ok(), [=] { box->closeBox(); }); + const auto container = box->verticalLayout(); + + const auto api = box->lifetime().make_state( + &peer->session().mtp()); + + using Flag = MTPmessages_translateText::Flag; + const auto flags = msgId + ? (Flag::f_peer | Flag::f_msg_id) + : !text.text.isEmpty() + ? Flag::f_text + : Flag(0); + + const auto &stLabel = st::aboutLabel; + const auto lineHeight = stLabel.style.lineHeight; + + Settings::AddSkip(container); + Settings::AddSubsectionTitle( + container, + tr::lng_translate_box_original()); + + const auto original = box->addRow(object_ptr>( + box, + object_ptr(box, stLabel))); + { + original->entity()->setMarkedText(text); + original->setMinimalHeight(lineHeight); + original->hide(anim::type::instant); + + const auto show = Ui::CreateChild>( + container.get(), + object_ptr(container)); + show->hide(anim::type::instant); + original->geometryValue( + ) | rpl::start_with_next([=](const QRect &rect) { + show->moveToLeft( + rect.x() + rect.width() - show->width(), + rect.y() + std::abs(lineHeight - show->height()) / 2); + }, show->lifetime()); + original->entity()->heightValue( + ) | rpl::filter([](int height) { + return height > 0; + }) | rpl::take(1) | rpl::start_with_next([=](int height) { + if (height > lineHeight) { + show->show(anim::type::instant); + } + }, show->lifetime()); + show->toggleOn(show->entity()->clicks() | rpl::map_to(false)); + original->toggleOn(show->entity()->clicks() | rpl::map_to(true)); + } + Settings::AddSkip(container); + Settings::AddSkip(container); + Settings::AddDivider(container); + Settings::AddSkip(container); + + Settings::AddSubsectionTitle( + container, + rpl::single(Lang::GetInstance().nativeName())); + + const auto translated = box->addRow(object_ptr>( + box, + object_ptr(box, stLabel))); + translated->entity()->setSelectable(true); + translated->hide(anim::type::instant); + + const auto showText = [=](const QString &text) { + translated->entity()->setText(text); + translated->show(anim::type::normal); + }; + + api->request(MTPmessages_TranslateText( + MTP_flags(flags), + msgId ? peer->input : MTP_inputPeerEmpty(), + MTP_int(msgId), + MTP_string(text.text), + MTPstring(), + MTP_string(Lang::LanguageIdOrDefault(Lang::Id())) + )).done([=](const MTPmessages_TranslatedText &result) { + const auto text = result.match([]( + const MTPDmessages_translateNoResult &data) { + return tr::lng_translate_box_error(tr::now); + }, [](const MTPDmessages_translateResultText &data) { + return qs(data.vtext()); + }); + showText(text); + }).fail([=](const MTP::Error &error) { + showText(tr::lng_translate_box_error(tr::now)); + }).send(); + +} + +} // namespace Ui diff --git a/Telegram/SourceFiles/boxes/translate_box.h b/Telegram/SourceFiles/boxes/translate_box.h new file mode 100644 index 0000000000..b4d59d4fdc --- /dev/null +++ b/Telegram/SourceFiles/boxes/translate_box.h @@ -0,0 +1,22 @@ +/* +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 + +class PeerData; + +namespace Ui { + +class GenericBox; + +void TranslateBox( + not_null box, + not_null peer, + MsgId msgId, + TextWithEntities text); + +} // namespace Ui diff --git a/Telegram/lib_ui b/Telegram/lib_ui index 3f28dfa821..e6064719df 160000 --- a/Telegram/lib_ui +++ b/Telegram/lib_ui @@ -1 +1 @@ -Subproject commit 3f28dfa821a85debe162c39ab64d1967f6029126 +Subproject commit e6064719dfb885910b73e0e90da8a66afa98f75a