mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2026-07-25 06:54:43 +00:00
Add translation bar dropdown menu.
This commit is contained in:
@@ -17,6 +17,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
#include "mtproto/sender.h"
|
||||
#include "settings/settings_common.h"
|
||||
#include "spellcheck/platform/platform_language.h"
|
||||
#include "ui/boxes/choose_language_box.h"
|
||||
#include "ui/effects/loading_element.h"
|
||||
#include "ui/layers/generic_box.h"
|
||||
#include "ui/painter.h"
|
||||
@@ -36,171 +37,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
namespace Ui {
|
||||
namespace {
|
||||
|
||||
[[nodiscard]] std::vector<QLocale::Language> Languages() {
|
||||
return std::vector<QLocale::Language>{
|
||||
QLocale::English,
|
||||
QLocale::Afrikaans,
|
||||
QLocale::Albanian,
|
||||
QLocale::Amharic,
|
||||
QLocale::Arabic,
|
||||
QLocale::Armenian,
|
||||
QLocale::Azerbaijani,
|
||||
QLocale::Basque,
|
||||
QLocale::Belarusian,
|
||||
QLocale::Bosnian,
|
||||
QLocale::Bulgarian,
|
||||
QLocale::Burmese,
|
||||
QLocale::Catalan,
|
||||
QLocale::Chinese,
|
||||
QLocale::Croatian,
|
||||
QLocale::Czech,
|
||||
QLocale::Danish,
|
||||
QLocale::Dutch,
|
||||
QLocale::Esperanto,
|
||||
QLocale::Estonian,
|
||||
QLocale::Finnish,
|
||||
QLocale::French,
|
||||
QLocale::Gaelic,
|
||||
QLocale::Galician,
|
||||
QLocale::Georgian,
|
||||
QLocale::German,
|
||||
QLocale::Greek,
|
||||
QLocale::Gusii,
|
||||
QLocale::Hausa,
|
||||
QLocale::Hebrew,
|
||||
QLocale::Hungarian,
|
||||
QLocale::Icelandic,
|
||||
QLocale::Igbo,
|
||||
QLocale::Indonesian,
|
||||
QLocale::Irish,
|
||||
QLocale::Italian,
|
||||
QLocale::Japanese,
|
||||
QLocale::Kazakh,
|
||||
QLocale::Kinyarwanda,
|
||||
QLocale::Korean,
|
||||
QLocale::Kurdish,
|
||||
QLocale::Lao,
|
||||
QLocale::Latvian,
|
||||
QLocale::Lithuanian,
|
||||
QLocale::Luxembourgish,
|
||||
QLocale::Macedonian,
|
||||
QLocale::Malagasy,
|
||||
QLocale::Malay,
|
||||
QLocale::Maltese,
|
||||
QLocale::Maori,
|
||||
QLocale::Mongolian,
|
||||
QLocale::Nepali,
|
||||
QLocale::Pashto,
|
||||
QLocale::Persian,
|
||||
QLocale::Polish,
|
||||
QLocale::Portuguese,
|
||||
QLocale::Romanian,
|
||||
QLocale::Russian,
|
||||
QLocale::Serbian,
|
||||
QLocale::Shona,
|
||||
QLocale::Sindhi,
|
||||
QLocale::Sinhala,
|
||||
QLocale::Slovak,
|
||||
QLocale::Slovenian,
|
||||
QLocale::Somali,
|
||||
QLocale::Spanish,
|
||||
QLocale::Sundanese,
|
||||
QLocale::Swahili,
|
||||
QLocale::Swedish,
|
||||
QLocale::Tajik,
|
||||
QLocale::Tatar,
|
||||
QLocale::Teso,
|
||||
QLocale::Thai,
|
||||
QLocale::Turkish,
|
||||
QLocale::Turkmen,
|
||||
QLocale::Ukrainian,
|
||||
QLocale::Urdu,
|
||||
QLocale::Uzbek,
|
||||
QLocale::Vietnamese,
|
||||
QLocale::Welsh,
|
||||
QLocale::WesternFrisian,
|
||||
QLocale::Xhosa,
|
||||
QLocale::Yiddish,
|
||||
};
|
||||
}
|
||||
|
||||
class Row final : public Ui::SettingsButton {
|
||||
public:
|
||||
Row(not_null<Ui::RpWidget*> parent, const QLocale &locale);
|
||||
|
||||
[[nodiscard]] bool filtered(const QString &query) const;
|
||||
[[nodiscard]] QLocale locale() const;
|
||||
|
||||
int resizeGetHeight(int newWidth) override;
|
||||
|
||||
protected:
|
||||
void paintEvent(QPaintEvent *e) override;
|
||||
|
||||
private:
|
||||
const style::PeerListItem &_st;
|
||||
const QLocale _locale;
|
||||
const QString _status;
|
||||
const QString _titleText;
|
||||
Ui::Text::String _title;
|
||||
|
||||
};
|
||||
|
||||
Row::Row(not_null<Ui::RpWidget*> parent, const QLocale &locale)
|
||||
: SettingsButton(parent, rpl::never<QString>())
|
||||
, _st(st::inviteLinkListItem)
|
||||
, _locale(locale)
|
||||
, _status(QLocale::languageToString(locale.language()))
|
||||
, _titleText(LanguageName(locale))
|
||||
, _title(_st.nameStyle, _titleText) {
|
||||
}
|
||||
|
||||
QLocale Row::locale() const {
|
||||
return _locale;
|
||||
}
|
||||
|
||||
bool Row::filtered(const QString &query) const {
|
||||
return _status.startsWith(query, Qt::CaseInsensitive)
|
||||
|| _titleText.startsWith(query, Qt::CaseInsensitive);
|
||||
}
|
||||
|
||||
int Row::resizeGetHeight(int newWidth) {
|
||||
return _st.height;
|
||||
}
|
||||
|
||||
void Row::paintEvent(QPaintEvent *e) {
|
||||
auto p = Painter(this);
|
||||
|
||||
const auto paintOver = (isOver() || isDown()) && !isDisabled();
|
||||
Ui::SettingsButton::paintBg(p, e->rect(), paintOver);
|
||||
Ui::SettingsButton::paintRipple(p, 0, 0);
|
||||
Ui::SettingsButton::paintToggle(p, width());
|
||||
|
||||
const auto &color = st::windowSubTextFg;
|
||||
p.setPen(Qt::NoPen);
|
||||
p.setBrush(color);
|
||||
|
||||
const auto left = st::settingsSubsectionTitlePadding.left();
|
||||
const auto toggleRect = Ui::SettingsButton::maybeToggleRect();
|
||||
const auto right = left
|
||||
+ (toggleRect.isEmpty() ? 0 : (width() - toggleRect.x()));
|
||||
|
||||
p.setPen(_st.nameFg);
|
||||
_title.drawLeft(
|
||||
p,
|
||||
left,
|
||||
_st.namePosition.y(),
|
||||
width() - left - right,
|
||||
width() - left - right);
|
||||
|
||||
p.setPen(paintOver ? _st.statusFgOver : _st.statusFg);
|
||||
p.setFont(st::contactsStatusFont);
|
||||
p.drawTextLeft(
|
||||
left,
|
||||
_st.statusPosition.y(),
|
||||
width() - left - right,
|
||||
_status);
|
||||
}
|
||||
|
||||
class ShowButton final : public RpWidget {
|
||||
public:
|
||||
ShowButton(not_null<Ui::RpWidget*> parent);
|
||||
@@ -250,19 +86,6 @@ rpl::producer<Qt::MouseButton> ShowButton::clicks() const {
|
||||
|
||||
} // namespace
|
||||
|
||||
QString LanguageName(const QLocale &locale) {
|
||||
if (locale.language() == QLocale::English
|
||||
&& (locale.country() == QLocale::UnitedStates
|
||||
|| locale.country() == QLocale::AnyCountry)) {
|
||||
return u"English"_q;
|
||||
} else if (locale.language() == QLocale::Spanish) {
|
||||
return QString::fromUtf8("\x45\x73\x70\x61\xc3\xb1\x6f\x6c");
|
||||
} else {
|
||||
const auto name = locale.nativeLanguageName();
|
||||
return name.left(1).toUpper() + name.mid(1);
|
||||
}
|
||||
}
|
||||
|
||||
void TranslateBox(
|
||||
not_null<Ui::GenericBox*> box,
|
||||
not_null<PeerData*> peer,
|
||||
@@ -272,14 +95,10 @@ void TranslateBox(
|
||||
box->setWidth(st::boxWideWidth);
|
||||
box->addButton(tr::lng_box_ok(), [=] { box->closeBox(); });
|
||||
const auto container = box->verticalLayout();
|
||||
const auto translateTo = Core::App().settings().translateTo().locale();
|
||||
|
||||
auto id = Core::App().settings().translateToValue();
|
||||
const auto api = box->lifetime().make_state<MTP::Sender>(
|
||||
&peer->session().mtp());
|
||||
struct State {
|
||||
rpl::event_stream<QLocale> locale;
|
||||
};
|
||||
const auto state = box->lifetime().make_state<State>();
|
||||
|
||||
text.entities = ranges::views::all(
|
||||
text.entities
|
||||
@@ -355,11 +174,10 @@ void TranslateBox(
|
||||
const auto padding = st::settingsSubsectionTitlePadding;
|
||||
const auto subtitle = Settings::AddSubsectionTitle(
|
||||
container,
|
||||
state->locale.events() | rpl::map(LanguageName));
|
||||
rpl::duplicate(id) | rpl::map(LanguageName));
|
||||
|
||||
// Workaround.
|
||||
state->locale.events(
|
||||
) | rpl::start_with_next([=] {
|
||||
rpl::duplicate(id) | rpl::start_with_next([=] {
|
||||
subtitle->resizeToWidth(container->width()
|
||||
- padding.left()
|
||||
- padding.right());
|
||||
@@ -370,7 +188,6 @@ void TranslateBox(
|
||||
box,
|
||||
object_ptr<FlatLabel>(box, stLabel)));
|
||||
translated->entity()->setSelectable(!hasCopyRestriction);
|
||||
translated->hide(anim::type::instant);
|
||||
|
||||
constexpr auto kMaxLines = 3;
|
||||
container->resizeToWidth(box->width());
|
||||
@@ -380,10 +197,9 @@ void TranslateBox(
|
||||
box,
|
||||
st::aboutLabel,
|
||||
std::min(original->entity()->height() / lineHeight, kMaxLines),
|
||||
state->locale.events() | rpl::map([=](const QLocale &locale) {
|
||||
return locale.textDirection() == Qt::RightToLeft;
|
||||
rpl::duplicate(id) | rpl::map([=](LanguageId id) {
|
||||
return id.locale().textDirection() == Qt::RightToLeft;
|
||||
}))));
|
||||
loading->show(anim::type::instant);
|
||||
|
||||
const auto showText = [=](const QString &text) {
|
||||
translated->entity()->setText(text);
|
||||
@@ -391,7 +207,9 @@ void TranslateBox(
|
||||
loading->hide(anim::type::instant);
|
||||
};
|
||||
|
||||
const auto send = [=](const QString &toLang) {
|
||||
const auto send = [=](LanguageId to) {
|
||||
loading->show(anim::type::instant);
|
||||
translated->hide(anim::type::instant);
|
||||
api->request(MTPmessages_TranslateText(
|
||||
MTP_flags(flags),
|
||||
msgId ? peer->input : MTP_inputPeerEmpty(),
|
||||
@@ -403,7 +221,7 @@ void TranslateBox(
|
||||
: MTP_vector<MTPTextWithEntities>(1, MTP_textWithEntities(
|
||||
MTP_string(text.text),
|
||||
MTP_vector<MTPMessageEntity>()))),
|
||||
MTP_string(toLang.mid(0, 2))
|
||||
MTP_string(to.locale().name().mid(0, 2))
|
||||
)).done([=](const MTPmessages_TranslatedText &result) {
|
||||
const auto &data = result.data();
|
||||
const auto &list = data.vresult().v;
|
||||
@@ -414,117 +232,16 @@ void TranslateBox(
|
||||
showText(tr::lng_translate_box_error(tr::now));
|
||||
}).send();
|
||||
};
|
||||
send(translateTo.name());
|
||||
state->locale.fire_copy(translateTo);
|
||||
std::move(id) | rpl::start_with_next(send, box->lifetime());
|
||||
|
||||
box->addLeftButton(tr::lng_settings_language(), [=] {
|
||||
if (loading->toggled()) {
|
||||
return;
|
||||
}
|
||||
Ui::BoxShow(box).showBox(Box(ChooseLanguageBox, [=](
|
||||
std::vector<QLocale> locales) {
|
||||
const auto &locale = locales.front();
|
||||
send(locale.name());
|
||||
state->locale.fire_copy(locale);
|
||||
loading->show(anim::type::instant);
|
||||
translated->hide(anim::type::instant);
|
||||
}, std::vector<QLocale>()));
|
||||
Ui::BoxShow(box).showBox(ChooseTranslateToBox());
|
||||
});
|
||||
}
|
||||
|
||||
void ChooseLanguageBox(
|
||||
not_null<Ui::GenericBox*> box,
|
||||
Fn<void(std::vector<QLocale>)> callback,
|
||||
std::vector<QLocale> toggled) {
|
||||
box->setMinHeight(st::boxWidth);
|
||||
box->setMaxHeight(st::boxWidth);
|
||||
box->setTitle(tr::lng_languages());
|
||||
|
||||
const auto hasToggled = !toggled.empty();
|
||||
|
||||
const auto multiSelect = box->setPinnedToTopContent(
|
||||
object_ptr<Ui::MultiSelect>(
|
||||
box,
|
||||
st::defaultMultiSelect,
|
||||
tr::lng_participant_filter()));
|
||||
box->setFocusCallback([=] { multiSelect->setInnerFocus(); });
|
||||
|
||||
const auto container = box->verticalLayout();
|
||||
const auto langs = [&] {
|
||||
auto langs = Languages();
|
||||
const auto current = QLocale(
|
||||
Lang::LanguageIdOrDefault(Lang::Id())).language();
|
||||
if (const auto it = ranges::find(langs, current); it != end(langs)) {
|
||||
base::reorder(langs, std::distance(begin(langs), it), 0);
|
||||
}
|
||||
return langs;
|
||||
}();
|
||||
auto rows = std::vector<not_null<Ui::SlideWrap<Row>*>>();
|
||||
rows.reserve(langs.size());
|
||||
for (const auto &lang : langs) {
|
||||
const auto locale = QLocale(lang);
|
||||
const auto button = container->add(
|
||||
object_ptr<Ui::SlideWrap<Row>>(
|
||||
container,
|
||||
object_ptr<Row>(container, locale)));
|
||||
if (hasToggled) {
|
||||
button->entity()->toggleOn(
|
||||
rpl::single(ranges::contains(toggled, locale)),
|
||||
false);
|
||||
} else {
|
||||
button->entity()->setClickedCallback([=] {
|
||||
callback({ locale });
|
||||
box->closeBox();
|
||||
});
|
||||
}
|
||||
rows.push_back(button);
|
||||
}
|
||||
|
||||
multiSelect->setQueryChangedCallback([=](const QString &query) {
|
||||
for (const auto &row : rows) {
|
||||
const auto toggled = row->entity()->filtered(query);
|
||||
if (toggled != row->toggled()) {
|
||||
row->toggle(toggled, anim::type::instant);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
{
|
||||
const auto label = Ui::CreateChild<Ui::FlatLabel>(
|
||||
box.get(),
|
||||
tr::lng_languages_none(),
|
||||
st::membersAbout);
|
||||
box->verticalLayout()->geometryValue(
|
||||
) | rpl::start_with_next([=](const QRect &geometry) {
|
||||
const auto shown = (geometry.height() <= 0);
|
||||
label->setVisible(shown);
|
||||
if (shown) {
|
||||
label->moveToLeft(
|
||||
(geometry.width() - label->width()) / 2,
|
||||
geometry.y() + st::membersAbout.style.font->height * 4);
|
||||
label->stackUnder(box->verticalLayout());
|
||||
}
|
||||
}, label->lifetime());
|
||||
}
|
||||
|
||||
if (hasToggled) {
|
||||
box->addButton(tr::lng_settings_save(), [=] {
|
||||
auto result = ranges::views::all(
|
||||
rows
|
||||
) | ranges::views::filter([](const auto &row) {
|
||||
return row->entity()->toggled();
|
||||
}) | ranges::views::transform([](const auto &row) {
|
||||
return row->entity()->locale();
|
||||
}) | ranges::to_vector;
|
||||
if (!result.empty()) {
|
||||
callback(std::move(result));
|
||||
}
|
||||
box->closeBox();
|
||||
});
|
||||
}
|
||||
box->addButton(tr::lng_cancel(), [=] { box->closeBox(); });
|
||||
}
|
||||
|
||||
bool SkipTranslate(TextWithEntities textWithEntities) {
|
||||
const auto &text = textWithEntities.text;
|
||||
if (text.isEmpty()) {
|
||||
@@ -557,4 +274,24 @@ bool SkipTranslate(TextWithEntities textWithEntities) {
|
||||
#endif
|
||||
}
|
||||
|
||||
object_ptr<BoxContent> EditSkipTranslationLanguages() {
|
||||
auto title = tr::lng_translate_settings_choose();
|
||||
return Box(ChooseLanguageBox, std::move(title), [=](
|
||||
std::vector<LanguageId> &&list) {
|
||||
Core::App().settings().setSkipTranslationLanguages(
|
||||
std::move(list));
|
||||
Core::App().saveSettingsDelayed();
|
||||
}, Core::App().settings().skipTranslationLanguages());
|
||||
}
|
||||
|
||||
object_ptr<BoxContent> ChooseTranslateToBox() {
|
||||
return Box(ChooseLanguageBox, tr::lng_languages(), [=](
|
||||
const std::vector<LanguageId> &ids) {
|
||||
Expects(!ids.empty());
|
||||
|
||||
Core::App().settings().setTranslateTo(ids.front());
|
||||
Core::App().saveSettingsDelayed();
|
||||
}, std::nullopt);
|
||||
}
|
||||
|
||||
} // namespace Ui
|
||||
|
||||
Reference in New Issue
Block a user