mirror of
https://github.com/telegramdesktop/tdesktop
synced 2025-03-23 11:47:57 +00:00
Add language and scale settings.
This commit is contained in:
parent
a7725f03bb
commit
3f543347b8
Telegram
Resources/langs
SourceFiles
@ -328,6 +328,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
"lng_settings_bg_tile" = "Tile background";
|
||||
"lng_settings_adaptive_wide" = "Adaptive layout for wide screens";
|
||||
|
||||
"lng_settings_language" = "Language";
|
||||
"lng_settings_default_scale" = "Default interface scale";
|
||||
|
||||
"lng_backgrounds_header" = "Choose your new chat background";
|
||||
"lng_theme_sure_keep" = "Keep this theme?";
|
||||
"lng_theme_reverting#one" = "Reverting to the old theme in {count} second.";
|
||||
|
@ -14,6 +14,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
#include "boxes/confirm_box.h"
|
||||
#include "mainwidget.h"
|
||||
#include "mainwindow.h"
|
||||
#include "messenger.h"
|
||||
#include "lang/lang_instance.h"
|
||||
#include "lang/lang_cloud_manager.h"
|
||||
#include "styles/style_boxes.h"
|
||||
@ -150,3 +151,27 @@ void LanguageBox::refreshLanguages() {
|
||||
}
|
||||
_inner->setSelected(currentIndex);
|
||||
}
|
||||
|
||||
base::binary_guard LanguageBox::Show() {
|
||||
auto result = base::binary_guard();
|
||||
|
||||
const auto manager = Messenger::Instance().langCloudManager();
|
||||
if (manager->languageList().isEmpty()) {
|
||||
auto guard = std::make_shared<base::binary_guard>();
|
||||
std::tie(result, *guard) = base::make_binary_guard();
|
||||
auto alive = std::make_shared<std::unique_ptr<base::Subscription>>(
|
||||
std::make_unique<base::Subscription>());
|
||||
**alive = manager->languageListChanged().add_subscription([=] {
|
||||
const auto show = guard->alive();
|
||||
*alive = nullptr;
|
||||
if (show) {
|
||||
Ui::show(Box<LanguageBox>());
|
||||
}
|
||||
});
|
||||
} else {
|
||||
Ui::show(Box<LanguageBox>());
|
||||
}
|
||||
manager->requestLanguageList();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
@ -10,6 +10,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
#include "lang/lang_cloud_manager.h"
|
||||
#include "boxes/abstract_box.h"
|
||||
#include "mtproto/sender.h"
|
||||
#include "base/binary_guard.h"
|
||||
|
||||
namespace Ui {
|
||||
class RadiobuttonGroup;
|
||||
@ -21,6 +22,8 @@ public:
|
||||
LanguageBox(QWidget*) {
|
||||
}
|
||||
|
||||
static base::binary_guard Show();
|
||||
|
||||
protected:
|
||||
void prepare() override;
|
||||
|
||||
|
@ -220,17 +220,8 @@ void GeneralWidget::onChangeLanguage() {
|
||||
Lang::CurrentCloudManager().switchToLanguage(qsl("custom"));
|
||||
return;
|
||||
}
|
||||
auto manager = Messenger::Instance().langCloudManager();
|
||||
if (manager->languageList().isEmpty()) {
|
||||
_languagesLoadedSubscription = subscribe(manager->languageListChanged(), [this] {
|
||||
unsubscribe(base::take(_languagesLoadedSubscription));
|
||||
Ui::show(Box<LanguageBox>());
|
||||
});
|
||||
} else {
|
||||
unsubscribe(base::take(_languagesLoadedSubscription));
|
||||
Ui::show(Box<LanguageBox>());
|
||||
}
|
||||
manager->requestLanguageList();
|
||||
|
||||
_languagesLoadWaiter = LanguageBox::Show();
|
||||
}
|
||||
|
||||
void GeneralWidget::onRestart() {
|
||||
|
@ -8,6 +8,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
#pragma once
|
||||
|
||||
#include "old_settings/settings_block_widget.h"
|
||||
#include "base/binary_guard.h"
|
||||
#include "ui/rp_widget.h"
|
||||
|
||||
namespace OldSettings {
|
||||
@ -98,7 +99,7 @@ private:
|
||||
Ui::SlideWrap<Ui::Checkbox> *_startMinimized = nullptr;
|
||||
Ui::Checkbox *_addInSendTo = nullptr;
|
||||
|
||||
int _languagesLoadedSubscription = 0;
|
||||
base::binary_guard _languagesLoadWaiter;
|
||||
|
||||
};
|
||||
|
||||
|
@ -10,3 +10,8 @@ using "ui/widgets/widgets.style";
|
||||
using "info/info.style";
|
||||
|
||||
settingsSectionButton: infoProfileButton;
|
||||
settingsSectionSkip: infoProfileSkip;
|
||||
settingsButtonRightPosition: point(28px, 10px);
|
||||
settingsButtonRight: FlatLabel(defaultFlatLabel) {
|
||||
textFg: windowActiveTextFg;
|
||||
}
|
||||
|
@ -9,13 +9,165 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
|
||||
#include "settings/settings_common.h"
|
||||
#include "boxes/abstract_box.h"
|
||||
#include "boxes/language_box.h"
|
||||
#include "boxes/confirm_box.h"
|
||||
#include "ui/wrap/vertical_layout.h"
|
||||
#include "ui/wrap/padding_wrap.h"
|
||||
#include "ui/widgets/labels.h"
|
||||
#include "ui/widgets/discrete_sliders.h"
|
||||
#include "info/profile/info_profile_button.h"
|
||||
#include "info/profile/info_profile_cover.h"
|
||||
#include "lang/lang_keys.h"
|
||||
#include "storage/localstorage.h"
|
||||
#include "styles/style_settings.h"
|
||||
|
||||
namespace Settings {
|
||||
namespace {
|
||||
|
||||
void AddSkip(not_null<Ui::VerticalLayout*> container) {
|
||||
container->add(object_ptr<Ui::FixedHeightWidget>(
|
||||
container,
|
||||
st::settingsSectionSkip));
|
||||
}
|
||||
|
||||
void AddDivider(not_null<Ui::VerticalLayout*> container) {
|
||||
container->add(object_ptr<BoxContentDivider>(container));
|
||||
}
|
||||
|
||||
void SetupLanguageButton(not_null<Ui::VerticalLayout*> container) {
|
||||
const auto button = container->add(object_ptr<Button>(
|
||||
container,
|
||||
Lang::Viewer(lng_settings_language),
|
||||
st::settingsSectionButton));
|
||||
const auto guard = Ui::AttachAsChild(button, base::binary_guard());
|
||||
button->addClickHandler([=] {
|
||||
*guard = LanguageBox::Show();
|
||||
});
|
||||
const auto name = Ui::CreateChild<Ui::FlatLabel>(
|
||||
button,
|
||||
Lang::Viewer(lng_language_name),
|
||||
st::settingsButtonRight);
|
||||
rpl::combine(
|
||||
name->widthValue(),
|
||||
button->widthValue()
|
||||
) | rpl::start_with_next([=] {
|
||||
name->moveToRight(
|
||||
st::settingsButtonRightPosition.x(),
|
||||
st::settingsButtonRightPosition.y());
|
||||
}, name->lifetime());
|
||||
}
|
||||
|
||||
void SetupInterfaceScale(not_null<Ui::VerticalLayout*> container) {
|
||||
if (cRetina()) {
|
||||
return;
|
||||
}
|
||||
AddDivider(container);
|
||||
AddSkip(container);
|
||||
|
||||
const auto toggled = Ui::AttachAsChild(
|
||||
container,
|
||||
rpl::event_stream<bool>());
|
||||
|
||||
const auto button = container->add(object_ptr<Button>(
|
||||
container,
|
||||
Lang::Viewer(lng_settings_default_scale),
|
||||
st::settingsSectionButton)
|
||||
)->toggleOn(toggled->events_starting_with(cConfigScale() == dbisAuto));
|
||||
|
||||
const auto slider = container->add(
|
||||
object_ptr<Ui::SettingsSlider>(container),
|
||||
st::settingsSectionButton.padding);
|
||||
|
||||
const auto inSetScale = Ui::AttachAsChild(container, false);
|
||||
const auto setScale = std::make_shared<Fn<void(DBIScale)>>();
|
||||
*setScale = [=](DBIScale scale) {
|
||||
if (*inSetScale) return;
|
||||
*inSetScale = true;
|
||||
const auto guard = gsl::finally([=] { *inSetScale = false; });
|
||||
|
||||
if (scale == cScreenScale()) {
|
||||
scale = dbisAuto;
|
||||
}
|
||||
toggled->fire(scale == dbisAuto);
|
||||
const auto applying = scale;
|
||||
if (scale == dbisAuto) {
|
||||
scale = cScreenScale();
|
||||
}
|
||||
slider->setActiveSection(scale - 1);
|
||||
|
||||
if (cEvalScale(scale) != cEvalScale(cRealScale())) {
|
||||
const auto confirmed = crl::guard(button, [=] {
|
||||
cSetConfigScale(scale);
|
||||
Local::writeSettings();
|
||||
App::restart();
|
||||
});
|
||||
const auto cancelled = crl::guard(button, [=] {
|
||||
App::CallDelayed(
|
||||
st::defaultSettingsSlider.duration,
|
||||
button,
|
||||
[=] { (*setScale)(cRealScale()); });
|
||||
});
|
||||
Ui::show(Box<ConfirmBox>(
|
||||
lang(lng_settings_need_restart),
|
||||
lang(lng_settings_restart_now),
|
||||
confirmed,
|
||||
cancelled));
|
||||
} else {
|
||||
cSetConfigScale(scale);
|
||||
Local::writeSettings();
|
||||
}
|
||||
};
|
||||
button->toggledValue(
|
||||
) | rpl::start_with_next([=](bool checked) {
|
||||
auto scale = checked ? dbisAuto : cEvalScale(cConfigScale());
|
||||
if (scale == cScreenScale()) {
|
||||
if (scale != cScale()) {
|
||||
scale = cScale();
|
||||
} else {
|
||||
switch (scale) {
|
||||
case dbisOne: scale = dbisOneAndQuarter; break;
|
||||
case dbisOneAndQuarter: scale = dbisOne; break;
|
||||
case dbisOneAndHalf: scale = dbisOneAndQuarter; break;
|
||||
case dbisTwo: scale = dbisOneAndHalf; break;
|
||||
}
|
||||
}
|
||||
}
|
||||
(*setScale)(scale);
|
||||
}, button->lifetime());
|
||||
|
||||
const auto label = [](DBIScale scale) {
|
||||
switch (scale) {
|
||||
case dbisOne: return qsl("100%");
|
||||
case dbisOneAndQuarter: return qsl("125%");
|
||||
case dbisOneAndHalf: return qsl("150%");
|
||||
case dbisTwo: return qsl("200%");
|
||||
}
|
||||
Unexpected("Value in scale label.");
|
||||
};
|
||||
const auto scaleByIndex = [](int index) {
|
||||
switch (index) {
|
||||
case 0: return dbisOne;
|
||||
case 1: return dbisOneAndQuarter;
|
||||
case 2: return dbisOneAndHalf;
|
||||
case 3: return dbisTwo;
|
||||
}
|
||||
Unexpected("Index in scaleByIndex.");
|
||||
};
|
||||
|
||||
slider->addSection(label(dbisOne));
|
||||
slider->addSection(label(dbisOneAndQuarter));
|
||||
slider->addSection(label(dbisOneAndHalf));
|
||||
slider->addSection(label(dbisTwo));
|
||||
slider->setActiveSectionFast(cEvalScale(cConfigScale()) - 1);
|
||||
slider->sectionActivated(
|
||||
) | rpl::start_with_next([=](int section) {
|
||||
(*setScale)(scaleByIndex(section));
|
||||
}, slider->lifetime());
|
||||
|
||||
AddSkip(container);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
Main::Main(
|
||||
QWidget *parent,
|
||||
@ -35,11 +187,19 @@ void Main::setupContent(not_null<Window::Controller*> controller) {
|
||||
controller));
|
||||
cover->setOnlineCount(rpl::single(0));
|
||||
|
||||
content->add(object_ptr<BoxContentDivider>(content));
|
||||
setupSections(content);
|
||||
SetupInterfaceScale(content);
|
||||
|
||||
Ui::ResizeFitChild(this, content);
|
||||
}
|
||||
|
||||
void Main::setupSections(not_null<Ui::VerticalLayout*> container) {
|
||||
AddDivider(container);
|
||||
AddSkip(container);
|
||||
|
||||
const auto addSection = [&](LangKey label, Type type) {
|
||||
content->add(object_ptr<Button>(
|
||||
content,
|
||||
container->add(object_ptr<Button>(
|
||||
container,
|
||||
Lang::Viewer(label),
|
||||
st::settingsSectionButton)
|
||||
)->addClickHandler([=] {
|
||||
@ -52,7 +212,9 @@ void Main::setupContent(not_null<Window::Controller*> controller) {
|
||||
addSection(lng_settings_section_general, Type::General);
|
||||
addSection(lng_settings_section_chat_settings, Type::Chat);
|
||||
|
||||
Ui::ResizeFitChild(this, content);
|
||||
SetupLanguageButton(container);
|
||||
|
||||
AddSkip(container);
|
||||
}
|
||||
|
||||
rpl::producer<Type> Main::sectionShowOther() {
|
||||
|
@ -13,6 +13,10 @@ namespace Window {
|
||||
class Controller;
|
||||
} // namespace Window
|
||||
|
||||
namespace Ui {
|
||||
class VerticalLayout;
|
||||
} // namespace Ui
|
||||
|
||||
namespace Settings {
|
||||
|
||||
class Main : public Section {
|
||||
@ -26,6 +30,7 @@ public:
|
||||
|
||||
private:
|
||||
void setupContent(not_null<Window::Controller*> controller);
|
||||
void setupSections(not_null<Ui::VerticalLayout*> container);
|
||||
|
||||
not_null<UserData*> _self;
|
||||
rpl::event_stream<Type> _showOther;
|
||||
|
@ -24,6 +24,10 @@ public:
|
||||
, _value(std::forward<OtherValue>(value)) {
|
||||
}
|
||||
|
||||
not_null<Value*> value() {
|
||||
return &_value;
|
||||
}
|
||||
|
||||
private:
|
||||
Value _value;
|
||||
|
||||
@ -57,11 +61,13 @@ void ResizeFitChild(
|
||||
not_null<RpWidget*> child);
|
||||
|
||||
template <typename Value>
|
||||
inline void AttachAsChild(not_null<QObject*> parent, Value &&value) {
|
||||
using PlainValue = std::decay_t<Value>;
|
||||
CreateChild<details::AttachmentOwner<PlainValue>>(
|
||||
inline not_null<std::decay_t<Value>*> AttachAsChild(
|
||||
not_null<QObject*> parent,
|
||||
Value &&value) {
|
||||
return CreateChild<details::AttachmentOwner<std::decay_t<Value>>>(
|
||||
parent.get(),
|
||||
std::forward<Value>(value));
|
||||
std::forward<Value>(value)
|
||||
)->value();
|
||||
}
|
||||
|
||||
template <typename Widget>
|
||||
|
@ -29,11 +29,15 @@ AbstractCheckView::AbstractCheckView(int duration, bool checked, Fn<void()> upda
|
||||
}
|
||||
|
||||
void AbstractCheckView::setCheckedFast(bool checked) {
|
||||
const auto fire = (_checked != checked);
|
||||
_checked = checked;
|
||||
finishAnimating();
|
||||
if (_updateCallback) {
|
||||
_updateCallback();
|
||||
}
|
||||
if (fire) {
|
||||
_checks.fire_copy(_checked);
|
||||
}
|
||||
}
|
||||
|
||||
void AbstractCheckView::setUpdateCallback(Fn<void()> updateCallback) {
|
||||
@ -53,6 +57,7 @@ void AbstractCheckView::setCheckedAnimated(bool checked) {
|
||||
if (_checked != checked) {
|
||||
_checked = checked;
|
||||
_toggleAnimation.start(_updateCallback, _checked ? 0. : 1., _checked ? 1. : 0., _duration);
|
||||
_checks.fire_copy(_checked);
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user