Add "Translate Entire Chat" button to Settings.

This commit is contained in:
John Preston 2023-01-30 18:01:10 +04:00
parent f5be551ff8
commit be71139515
14 changed files with 148 additions and 78 deletions

View file

@ -7,6 +7,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/ */
#include "boxes/language_box.h" #include "boxes/language_box.h"
#include "data/data_peer_values.h"
#include "lang/lang_keys.h" #include "lang/lang_keys.h"
#include "ui/boxes/choose_language_box.h" #include "ui/boxes/choose_language_box.h"
#include "ui/widgets/checkbox.h" #include "ui/widgets/checkbox.h"
@ -24,8 +25,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/text/text_options.h" #include "ui/text/text_options.h"
#include "ui/painter.h" #include "ui/painter.h"
#include "storage/localstorage.h" #include "storage/localstorage.h"
#include "boxes/premium_preview_box.h"
#include "boxes/translate_box.h" #include "boxes/translate_box.h"
#include "ui/boxes/confirm_box.h" #include "ui/boxes/confirm_box.h"
#include "main/main_session.h"
#include "mainwidget.h" #include "mainwidget.h"
#include "mainwindow.h" #include "mainwindow.h"
#include "core/application.h" #include "core/application.h"
@ -33,6 +36,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "lang/lang_cloud_manager.h" #include "lang/lang_cloud_manager.h"
#include "settings/settings_common.h" #include "settings/settings_common.h"
#include "spellcheck/spellcheck_types.h" #include "spellcheck/spellcheck_types.h"
#include "window/window_session_controller.h"
#include "styles/style_layers.h" #include "styles/style_layers.h"
#include "styles/style_boxes.h" #include "styles/style_boxes.h"
#include "styles/style_info.h" #include "styles/style_info.h"
@ -1095,58 +1099,17 @@ Ui::ScrollToRequest Content::jump(int rows) {
} // namespace } // namespace
LanguageBox::LanguageBox(QWidget*, Window::SessionController *controller)
: _controller(controller) {
}
void LanguageBox::prepare() { void LanguageBox::prepare() {
addButton(tr::lng_box_ok(), [=] { closeBox(); }); addButton(tr::lng_box_ok(), [=] { closeBox(); });
setTitle(tr::lng_languages()); setTitle(tr::lng_languages());
const auto topContainer = Ui::CreateChild<Ui::VerticalLayout>(this); const auto topContainer = Ui::CreateChild<Ui::VerticalLayout>(this);
Settings::AddSubsectionTitle( setupTop(topContainer);
topContainer,
tr::lng_translate_settings_subtitle());
const auto translateEnabled = Settings::AddButton(
topContainer,
tr::lng_translate_settings_show(),
st::settingsButtonNoIcon
)->toggleOn(rpl::single(Core::App().settings().translateButtonEnabled()));
translateEnabled->toggledValue(
) | rpl::filter([](bool checked) {
return (checked != Core::App().settings().translateButtonEnabled());
}) | rpl::start_with_next([=](bool checked) {
Core::App().settings().setTranslateButtonEnabled(checked);
Core::App().saveSettingsDelayed();
}, translateEnabled->lifetime());
using Languages = std::vector<LanguageId>;
const auto translateSkipWrap = topContainer->add(
object_ptr<Ui::SlideWrap<Ui::VerticalLayout>>(
topContainer,
object_ptr<Ui::VerticalLayout>(topContainer)));
translateSkipWrap->toggle(
translateEnabled->toggled(),
anim::type::normal);
translateSkipWrap->toggleOn(translateEnabled->toggledValue());
const auto translateSkip = Settings::AddButtonWithLabel(
translateSkipWrap->entity(),
tr::lng_translate_settings_choose(),
Core::App().settings().skipTranslationLanguagesValue(
) | rpl::map([](const Languages &list) {
return (list.size() > 1)
? tr::lng_languages_count(tr::now, lt_count, list.size())
: Ui::LanguageName(list.front());
}),
st::settingsButtonNoIcon);
translateSkip->setClickedCallback([=] {
Ui::BoxShow(this).showBox(Ui::EditSkipTranslationLanguages());
});
Settings::AddSkip(topContainer);
Settings::AddDividerText(
topContainer,
tr::lng_translate_settings_about());
const auto select = topContainer->add( const auto select = topContainer->add(
object_ptr<Ui::MultiSelect>( object_ptr<Ui::MultiSelect>(
topContainer, topContainer,
@ -1210,6 +1173,86 @@ void LanguageBox::prepare() {
}; };
} }
void LanguageBox::setupTop(not_null<Ui::VerticalLayout*> container) {
if (!_controller) {
return;
}
const auto translateEnabled = Settings::AddButton(
container,
tr::lng_translate_settings_show(),
st::settingsButtonNoIcon
)->toggleOn(
rpl::single(Core::App().settings().translateButtonEnabled()));
translateEnabled->toggledValue(
) | rpl::filter([](bool checked) {
return (checked != Core::App().settings().translateButtonEnabled());
}) | rpl::start_with_next([=](bool checked) {
Core::App().settings().setTranslateButtonEnabled(checked);
Core::App().saveSettingsDelayed();
}, translateEnabled->lifetime());
using namespace rpl::mappers;
auto premium = Data::AmPremiumValue(&_controller->session());
const auto translateChat = Settings::AddButton(
container,
tr::lng_translate_settings_chat(),
st::settingsButtonNoIconLocked
)->toggleOn(rpl::merge(
rpl::combine(
Core::App().settings().translateChatEnabledValue(),
rpl::duplicate(premium),
_1 && _2),
_translateChatTurnOff.events()));
std::move(premium) | rpl::start_with_next([=](bool value) {
translateChat->setToggleLocked(!value);
}, translateChat->lifetime());
translateChat->toggledValue(
) | rpl::filter([=](bool checked) {
const auto premium = _controller->session().premium();
if (checked && !premium) {
ShowPremiumPreviewToBuy(
_controller,
PremiumPreview::RealTimeTranslation);
_translateChatTurnOff.fire(false);
}
return premium
&& (checked != Core::App().settings().translateChatEnabled());
}) | rpl::start_with_next([=](bool checked) {
Core::App().settings().setTranslateChatEnabled(checked);
Core::App().saveSettingsDelayed();
}, translateChat->lifetime());
using Languages = std::vector<LanguageId>;
const auto translateSkipWrap = container->add(
object_ptr<Ui::SlideWrap<Ui::VerticalLayout>>(
container,
object_ptr<Ui::VerticalLayout>(container)));
translateSkipWrap->toggle(
translateEnabled->toggled(),
anim::type::normal);
translateSkipWrap->toggleOn(translateEnabled->toggledValue());
const auto translateSkip = Settings::AddButtonWithLabel(
translateSkipWrap->entity(),
tr::lng_translate_settings_choose(),
Core::App().settings().skipTranslationLanguagesValue(
) | rpl::map([](const Languages &list) {
return (list.size() > 1)
? tr::lng_languages_count(tr::now, lt_count, list.size())
: Ui::LanguageName(list.front());
}),
st::settingsButtonNoIcon);
translateSkip->setClickedCallback([=] {
Ui::BoxShow(this).showBox(Ui::EditSkipTranslationLanguages());
});
Settings::AddSkip(container);
Settings::AddDividerText(
container,
tr::lng_translate_settings_about());
}
void LanguageBox::keyPressEvent(QKeyEvent *e) { void LanguageBox::keyPressEvent(QKeyEvent *e) {
const auto key = e->key(); const auto key = e->key();
if (key == Qt::Key_Escape) { if (key == Qt::Key_Escape) {
@ -1241,11 +1284,12 @@ void LanguageBox::setInnerFocus() {
_setInnerFocus(); _setInnerFocus();
} }
base::binary_guard LanguageBox::Show() { base::binary_guard LanguageBox::Show(Window::SessionController *controller) {
auto result = base::binary_guard(); auto result = base::binary_guard();
auto &manager = Lang::CurrentCloudManager(); auto &manager = Lang::CurrentCloudManager();
if (manager.languageList().empty()) { if (manager.languageList().empty()) {
const auto weak = base::make_weak(controller);
auto guard = std::make_shared<base::binary_guard>( auto guard = std::make_shared<base::binary_guard>(
result.make_guard()); result.make_guard());
auto lifetime = std::make_shared<rpl::lifetime>(); auto lifetime = std::make_shared<rpl::lifetime>();
@ -1258,11 +1302,11 @@ base::binary_guard LanguageBox::Show() {
base::take(lifetime)->destroy(); base::take(lifetime)->destroy();
} }
if (show) { if (show) {
Ui::show(Box<LanguageBox>()); Ui::show(Box<LanguageBox>(weak.get()));
} }
}, *lifetime); }, *lifetime);
} else { } else {
Ui::show(Box<LanguageBox>()); Ui::show(Box<LanguageBox>(controller));
} }
manager.requestLanguageList(); manager.requestLanguageList();

View file

@ -16,16 +16,20 @@ struct LanguageId;
namespace Ui { namespace Ui {
class MultiSelect; class MultiSelect;
struct ScrollToRequest; struct ScrollToRequest;
class VerticalLayout;
} // namespace Ui } // namespace Ui
namespace Window {
class SessionController;
} // namespace Window
class LanguageBox : public Ui::BoxContent { class LanguageBox : public Ui::BoxContent {
public: public:
LanguageBox(QWidget*) { LanguageBox(QWidget*, Window::SessionController *controller);
}
void setInnerFocus() override; void setInnerFocus() override;
static base::binary_guard Show(); static base::binary_guard Show(Window::SessionController *controller);
protected: protected:
void prepare() override; void prepare() override;
@ -35,8 +39,11 @@ protected:
private: private:
using Languages = Lang::CloudManager::Languages; using Languages = Lang::CloudManager::Languages;
int rowsInPage() const; void setupTop(not_null<Ui::VerticalLayout*> container);
[[nodiscard]] int rowsInPage() const;
Window::SessionController *_controller = nullptr;
rpl::event_stream<bool> _translateChatTurnOff;
Fn<void()> _setInnerFocus; Fn<void()> _setInnerFocus;
Fn<Ui::ScrollToRequest(int rows)> _jump; Fn<Ui::ScrollToRequest(int rows)> _jump;

View file

@ -62,7 +62,7 @@ void ShowPremiumPreviewBox(
void ShowPremiumPreviewToBuy( void ShowPremiumPreviewToBuy(
not_null<Window::SessionController*> controller, not_null<Window::SessionController*> controller,
PremiumPreview section, PremiumPreview section,
Fn<void()> hiddenCallback); Fn<void()> hiddenCallback = nullptr);
void PremiumUnavailableBox(not_null<Ui::GenericBox*> box); void PremiumUnavailableBox(not_null<Ui::GenericBox*> box);

View file

@ -384,18 +384,22 @@ void Application::showAccount(not_null<Main::Account*> account) {
_lastActivePrimaryWindow = separate; _lastActivePrimaryWindow = separate;
separate->activate(); separate->activate();
} else if (const auto last = activePrimaryWindow()) { } else if (const auto last = activePrimaryWindow()) {
for (auto &[key, window] : _primaryWindows) {
if (window.get() == last && key != account.get()) {
auto found = std::move(window);
_primaryWindows.remove(key);
_primaryWindows.emplace(account, std::move(found));
break;
}
}
last->showAccount(account); last->showAccount(account);
} }
} }
void Application::checkWindowAccount(not_null<Window::Controller*> window) {
const auto account = window->maybeAccount();
for (auto &[key, existing] : _primaryWindows) {
if (existing.get() == window && key != account) {
auto found = std::move(existing);
_primaryWindows.remove(key);
_primaryWindows.emplace(account, std::move(found));
break;
}
}
}
void Application::showOpenGLCrashNotification() { void Application::showOpenGLCrashNotification() {
const auto enable = [=] { const auto enable = [=] {
Ui::GL::ForceDisable(false); Ui::GL::ForceDisable(false);

View file

@ -181,6 +181,7 @@ public:
void checkSystemDarkMode(); void checkSystemDarkMode();
[[nodiscard]] bool isActiveForTrayMenu() const; [[nodiscard]] bool isActiveForTrayMenu() const;
void closeChatFromWindows(not_null<PeerData*> peer); void closeChatFromWindows(not_null<PeerData*> peer);
void checkWindowAccount(not_null<Window::Controller*> window);
void activate(); void activate();
// Media view interface. // Media view interface.

View file

@ -113,9 +113,9 @@ bool ShowTheme(
return true; return true;
} }
void ShowLanguagesBox() { void ShowLanguagesBox(Window::SessionController *controller) {
static auto Guard = base::binary_guard(); static auto Guard = base::binary_guard();
Guard = LanguageBox::Show(); Guard = LanguageBox::Show(controller);
} }
bool SetLanguage( bool SetLanguage(
@ -123,7 +123,7 @@ bool SetLanguage(
const Match &match, const Match &match,
const QVariant &context) { const QVariant &context) {
if (match->capturedView(1).isEmpty()) { if (match->capturedView(1).isEmpty()) {
ShowLanguagesBox(); ShowLanguagesBox(controller);
} else { } else {
const auto languageId = match->captured(2); const auto languageId = match->captured(2);
Lang::CurrentCloudManager().switchWithWarning(languageId); Lang::CurrentCloudManager().switchWithWarning(languageId);
@ -468,18 +468,12 @@ bool ResolveSettings(
Window::SessionController *controller, Window::SessionController *controller,
const Match &match, const Match &match,
const QVariant &context) { const QVariant &context) {
if (!controller) {
return false;
}
controller->window().activate();
const auto section = match->captured(1).mid(1).toLower(); const auto section = match->captured(1).mid(1).toLower();
const auto type = [&]() -> std::optional<::Settings::Type> { const auto type = [&]() -> std::optional<::Settings::Type> {
if (section == u"language"_q) { if (section == u"language"_q) {
ShowLanguagesBox(); ShowLanguagesBox(controller);
return {}; return {};
} else if (section == u"devices"_q) { } else if (section == u"devices"_q) {
controller->session().api().authorizations().reload();
return ::Settings::Sessions::Id(); return ::Settings::Sessions::Id();
} else if (section == u"folders"_q) { } else if (section == u"folders"_q) {
return ::Settings::Folders::Id(); return ::Settings::Folders::Id();
@ -498,6 +492,11 @@ bool ResolveSettings(
}(); }();
if (type.has_value()) { if (type.has_value()) {
if (!controller) {
return false;
} else if (*type == ::Settings::Sessions::Id()) {
controller->session().api().authorizations().reload();
}
controller->showSettings(*type); controller->showSettings(*type);
controller->window().activate(); controller->window().activate();
} }

View file

@ -57,7 +57,11 @@ void TranslateTracker::setup() {
const auto session = &_history->session(); const auto session = &_history->session();
peer->updateFull(); peer->updateFull();
_trackingLanguage = Data::AmPremiumValue(&_history->session()); using namespace rpl::mappers;
_trackingLanguage = rpl::combine(
Data::AmPremiumValue(&_history->session()),
Core::App().settings().translateChatEnabledValue(),
_1 && _2);
_trackingLanguage.value( _trackingLanguage.value(
) | rpl::start_with_next([=](bool tracking) { ) | rpl::start_with_next([=](bool tracking) {

View file

@ -1278,7 +1278,7 @@ bool MainWidget::showHistoryInDifferentWindow(
} else if (isPrimary()) { } else if (isPrimary()) {
const auto primary = Core::App().separateWindowForAccount( const auto primary = Core::App().separateWindowForAccount(
&peer->account()); &peer->account());
if (primary != &_controller->window()) { if (primary && primary != &_controller->window()) {
primary->sessionController()->showPeerHistory( primary->sessionController()->showPeerHistory(
peerId, peerId,
params, params,

View file

@ -22,6 +22,14 @@ settingsButtonLight: SettingsButton(settingsButton) {
settingsButtonNoIcon: SettingsButton(settingsButton) { settingsButtonNoIcon: SettingsButton(settingsButton) {
padding: margins(22px, 10px, 22px, 8px); padding: margins(22px, 10px, 22px, 8px);
} }
settingsButtonNoIconLocked : SettingsButton(settingsButtonNoIcon) {
toggle: Toggle(infoProfileToggle) {
lockIcon: icon {{ "info/info_rights_lock", menuIconFg }};
}
toggleOver: Toggle(infoProfileToggleOver) {
lockIcon: icon {{ "info/info_rights_lock", menuIconFgOver }};
}
}
settingsButtonActive: SettingsButton(infoMainButton, settingsButton) { settingsButtonActive: SettingsButton(infoMainButton, settingsButton) {
} }
settingsAttentionButton: SettingsButton(settingsButtonNoIcon) { settingsAttentionButton: SettingsButton(settingsButtonNoIcon) {

View file

@ -63,7 +63,7 @@ object_ptr<Ui::RpWidget> CreateIntroSettings(
AddDivider(result); AddDivider(result);
AddSkip(result); AddSkip(result);
SetupLanguageButton(result, false); SetupLanguageButton(window, result, false);
SetupConnectionType(window, &window->account(), result); SetupConnectionType(window, &window->account(), result);
AddSkip(result); AddSkip(result);
if (HasUpdate()) { if (HasUpdate()) {

View file

@ -251,6 +251,7 @@ void Cover::refreshUsernameGeometry(int newWidth) {
} // namespace } // namespace
void SetupLanguageButton( void SetupLanguageButton(
not_null<Window::Controller*> window,
not_null<Ui::VerticalLayout*> container, not_null<Ui::VerticalLayout*> container,
bool icon) { bool icon) {
const auto button = AddButtonWithLabel( const auto button = AddButtonWithLabel(
@ -269,7 +270,7 @@ void SetupLanguageButton(
if ((m & Qt::ShiftModifier) && (m & Qt::AltModifier)) { if ((m & Qt::ShiftModifier) && (m & Qt::AltModifier)) {
Lang::CurrentCloudManager().switchToLanguage({ u"#custom"_q }); Lang::CurrentCloudManager().switchToLanguage({ u"#custom"_q });
} else { } else {
*guard = LanguageBox::Show(); *guard = LanguageBox::Show(window->sessionController());
} }
}); });
} }
@ -373,7 +374,7 @@ void SetupSections(
Calls::Id(), Calls::Id(),
{ &st::settingsIconCalls, kIconGreen }); { &st::settingsIconCalls, kIconGreen });
SetupLanguageButton(container); SetupLanguageButton(&controller->window(), container);
if (controller->session().premiumPossible()) { if (controller->session().premiumPossible()) {
AddSkip(container); AddSkip(container);

View file

@ -21,6 +21,7 @@ class VerticalLayout;
namespace Settings { namespace Settings {
void SetupLanguageButton( void SetupLanguageButton(
not_null<Window::Controller*> window,
not_null<Ui::VerticalLayout*> container, not_null<Ui::VerticalLayout*> container,
bool icon = true); bool icon = true);
bool HasInterfaceScale(); bool HasInterfaceScale();

View file

@ -86,6 +86,7 @@ void Controller::showAccount(
: 0; : 0;
_accountLifetime.destroy(); _accountLifetime.destroy();
_account = account; _account = account;
Core::App().checkWindowAccount(this);
const auto updateOnlineOfPrevSesssion = crl::guard(_account, [=] { const auto updateOnlineOfPrevSesssion = crl::guard(_account, [=] {
if (!prevSessionUniqueId) { if (!prevSessionUniqueId) {

@ -1 +1 @@
Subproject commit 46385c35458d41ce589a75db51f320842794e31a Subproject commit 55ed1489ffac0b60adbd427c2b76be1ce55194e7