mirror of https://github.com/procxx/kepka.git
Improve new settings design.
This commit is contained in:
parent
ffc4cd3415
commit
c2039da600
Binary file not shown.
Before Width: | Height: | Size: 408 B |
Binary file not shown.
Before Width: | Height: | Size: 1.2 KiB |
|
@ -267,7 +267,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
"lng_bio_placeholder" = "Bio";
|
||||
"lng_bio_about" = "You can add a few lines about yourself. Anyone who opens your profile will see this text.";
|
||||
|
||||
"lng_settings_section_info" = "Info";
|
||||
"lng_settings_section_info" = "My info";
|
||||
"lng_settings_username" = "Username:";
|
||||
"lng_settings_choose_username" = "Choose username";
|
||||
"lng_settings_empty_bio" = "None";
|
||||
|
@ -353,6 +353,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
"lng_settings_calls_title" = "Calls";
|
||||
"lng_settings_peer_to_peer" = "Peer-to-Peer";
|
||||
"lng_settings_peer_to_peer_about" = "Disabling peer-to-peer will relay all calls through Telegram servers to avoid revealing your IP address, but may slightly decrease audio quality.";
|
||||
"lng_settings_advanced" = "Advanced";
|
||||
"lng_settings_stickers_emoji" = "Stickers and emoji";
|
||||
"lng_settings_themes" = "Themes";
|
||||
"lng_settings_chat_other" = "Other";
|
||||
|
||||
"lng_backgrounds_header" = "Choose your new chat background";
|
||||
"lng_theme_sure_keep" = "Keep this theme?";
|
||||
|
|
|
@ -192,7 +192,7 @@ void LocalStorageBox::Row::step_radial(TimeMs ms, bool timer) {
|
|||
}
|
||||
|
||||
rpl::producer<> LocalStorageBox::Row::clearRequests() const {
|
||||
return _clear->clicks();
|
||||
return _clear->clicks() | rpl::map([] { return rpl::empty_value(); });
|
||||
}
|
||||
|
||||
int LocalStorageBox::Row::resizeGetHeight(int newWidth) {
|
||||
|
|
|
@ -266,7 +266,7 @@ ProgressWidget::ProgressWidget(
|
|||
|
||||
rpl::producer<> ProgressWidget::cancelClicks() const {
|
||||
return _cancel
|
||||
? _cancel->clicks()
|
||||
? (_cancel->clicks() | rpl::map([] { return rpl::empty_value(); }))
|
||||
: (rpl::never<>() | rpl::type_erased());
|
||||
}
|
||||
|
||||
|
@ -322,7 +322,10 @@ void ProgressWidget::showDone() {
|
|||
if (_done->width() < desired) {
|
||||
_done->setFullWidth(desired);
|
||||
}
|
||||
_done->clicks() | rpl::start_to_stream(_doneClicks, _done->lifetime());
|
||||
_done->clicks(
|
||||
) | rpl::map([] {
|
||||
return rpl::empty_value();
|
||||
}) | rpl::start_to_stream(_doneClicks, _done->lifetime());
|
||||
setupBottomButton(_done.get());
|
||||
}
|
||||
|
||||
|
|
|
@ -524,7 +524,10 @@ void SettingsWidget::refreshButtons(
|
|||
: nullptr;
|
||||
if (start) {
|
||||
start->show();
|
||||
_startClicks = start->clicks();
|
||||
_startClicks = start->clicks(
|
||||
) | rpl::map([] {
|
||||
return rpl::empty_value();
|
||||
});
|
||||
|
||||
container->sizeValue(
|
||||
) | rpl::start_with_next([=](QSize size) {
|
||||
|
@ -539,7 +542,10 @@ void SettingsWidget::refreshButtons(
|
|||
langFactory(lng_cancel),
|
||||
st::defaultBoxButton);
|
||||
cancel->show();
|
||||
_cancelClicks = cancel->clicks();
|
||||
_cancelClicks = cancel->clicks(
|
||||
) | rpl::map([] {
|
||||
return rpl::empty_value();
|
||||
});
|
||||
|
||||
rpl::combine(
|
||||
container->sizeValue(),
|
||||
|
|
|
@ -30,7 +30,7 @@ TopBar::TopBar(QWidget *parent, Content &&content)
|
|||
updateData(std::move(content));
|
||||
}
|
||||
|
||||
rpl::producer<> TopBar::clicks() const {
|
||||
rpl::producer<Qt::MouseButton> TopBar::clicks() const {
|
||||
return _button->clicks();
|
||||
}
|
||||
|
||||
|
|
|
@ -25,7 +25,7 @@ class TopBar : public Ui::RpWidget {
|
|||
public:
|
||||
TopBar(QWidget *parent, Content &&content);
|
||||
|
||||
rpl::producer<> clicks() const;
|
||||
rpl::producer<Qt::MouseButton> clicks() const;
|
||||
|
||||
void updateData(Content &&content);
|
||||
|
||||
|
|
|
@ -50,7 +50,7 @@ public:
|
|||
|
||||
rpl::producer<int> scrollHeightValue() const;
|
||||
rpl::producer<int> desiredHeightValue() const override;
|
||||
rpl::producer<bool> desiredShadowVisibility() const;
|
||||
virtual rpl::producer<bool> desiredShadowVisibility() const;
|
||||
bool hasTopBarShadow() const;
|
||||
|
||||
virtual void setInnerFocus();
|
||||
|
|
|
@ -99,8 +99,10 @@ void TopBar::enableBackButton() {
|
|||
st::infoTopBarScale);
|
||||
_back->setDuration(st::infoTopBarDuration);
|
||||
_back->toggle(!selectionMode(), anim::type::instant);
|
||||
_back->entity()->clicks()
|
||||
| rpl::start_to_stream(_backClicks, _back->lifetime());
|
||||
_back->entity()->clicks(
|
||||
) | rpl::map([] {
|
||||
return rpl::empty_value();
|
||||
}) | rpl::start_to_stream(_backClicks, _back->lifetime());
|
||||
registerToggleControlCallback(_back.data(), [=] {
|
||||
return !selectionMode();
|
||||
});
|
||||
|
@ -434,7 +436,9 @@ void TopBar::createSelectionControls() {
|
|||
st::infoTopBarScale));
|
||||
_cancelSelection->setDuration(st::infoTopBarDuration);
|
||||
_cancelSelection->entity()->clicks(
|
||||
) | rpl::start_to_stream(
|
||||
) | rpl::map([] {
|
||||
return rpl::empty_value();
|
||||
}) | rpl::start_to_stream(
|
||||
_cancelSelectionClicks,
|
||||
_cancelSelection->lifetime());
|
||||
_selectionText = wrap(Ui::CreateChild<Ui::FadeWrap<Ui::LabelWithNumbers>>(
|
||||
|
@ -605,7 +609,7 @@ rpl::producer<QString> TitleValue(
|
|||
case Section::SettingsType::PrivacySecurity:
|
||||
return lng_settings_section_privacy;
|
||||
case Section::SettingsType::General:
|
||||
return lng_settings_section_general;
|
||||
return lng_settings_advanced;
|
||||
case Section::SettingsType::Chat:
|
||||
return lng_settings_section_chat_settings;
|
||||
}
|
||||
|
|
|
@ -71,7 +71,7 @@ void Button::paintEvent(QPaintEvent *e) {
|
|||
Painter p(this);
|
||||
|
||||
auto ms = getms();
|
||||
auto paintOver = (isOver() || isDown());
|
||||
auto paintOver = (isOver() || isDown()) && !isDisabled();
|
||||
p.fillRect(e->rect(), paintOver ? _st.textBgOver : _st.textBg);
|
||||
|
||||
paintRipple(p, 0, 0, ms);
|
||||
|
@ -113,10 +113,13 @@ int Button::resizeGetHeight(int newWidth) {
|
|||
void Button::onStateChanged(
|
||||
State was,
|
||||
StateChangeSource source) {
|
||||
RippleButton::onStateChanged(was, source);
|
||||
if (!isDisabled() || !isDown()) {
|
||||
RippleButton::onStateChanged(was, source);
|
||||
}
|
||||
if (_toggle) {
|
||||
_toggle->setStyle(isOver() ? _st.toggleOver : _st.toggle);
|
||||
}
|
||||
setPointerCursor(!isDisabled());
|
||||
}
|
||||
|
||||
void Button::setText(QString &&text) {
|
||||
|
|
|
@ -294,6 +294,8 @@ void Cover::initViewers() {
|
|||
) | rpl::start_with_next(
|
||||
[this] { refreshUploadPhotoOverlay(); },
|
||||
lifetime());
|
||||
} else if (_peer->isSelf()) {
|
||||
refreshUploadPhotoOverlay();
|
||||
}
|
||||
VerifiedValue(
|
||||
_peer
|
||||
|
@ -304,12 +306,12 @@ void Cover::initViewers() {
|
|||
|
||||
void Cover::refreshUploadPhotoOverlay() {
|
||||
_userpic->switchChangePhotoOverlay([&] {
|
||||
if (auto chat = _peer->asChat()) {
|
||||
if (const auto chat = _peer->asChat()) {
|
||||
return chat->canEdit();
|
||||
} else if (auto channel = _peer->asChannel()) {
|
||||
} else if (const auto channel = _peer->asChannel()) {
|
||||
return channel->canEditInformation();
|
||||
}
|
||||
return false;
|
||||
return _peer->isSelf();
|
||||
}());
|
||||
}
|
||||
|
||||
|
|
|
@ -86,6 +86,12 @@ void Widget::saveChanges(FnMut<void()> done) {
|
|||
_inner->sectionSaveChanges(std::move(done));
|
||||
}
|
||||
|
||||
rpl::producer<bool> Widget::desiredShadowVisibility() const {
|
||||
return (_type == Type::Main || _type == Type::Information)
|
||||
? ContentWidget::desiredShadowVisibility()
|
||||
: rpl::single(true);
|
||||
}
|
||||
|
||||
std::unique_ptr<ContentMemento> Widget::doCreateMemento() {
|
||||
auto result = std::make_unique<Memento>(self(), _type);
|
||||
saveState(result.get());
|
||||
|
|
|
@ -66,6 +66,8 @@ public:
|
|||
rpl::producer<bool> canSaveChanges() const override;
|
||||
void saveChanges(FnMut<void()> done) override;
|
||||
|
||||
rpl::producer<bool> desiredShadowVisibility() const override;
|
||||
|
||||
private:
|
||||
void saveState(not_null<Memento*> memento);
|
||||
void restoreState(not_null<Memento*> memento);
|
||||
|
|
|
@ -81,10 +81,12 @@ public:
|
|||
void setError(bool error);
|
||||
|
||||
rpl::producer<> deleteClicks() const {
|
||||
return _delete->entity()->clicks();
|
||||
return _delete->entity()->clicks(
|
||||
) | rpl::map([] { return rpl::empty_value(); });
|
||||
}
|
||||
rpl::producer<> restoreClicks() const {
|
||||
return _restore->entity()->clicks();
|
||||
return _restore->entity()->clicks(
|
||||
) | rpl::map([] { return rpl::empty_value(); });
|
||||
}
|
||||
|
||||
protected:
|
||||
|
|
|
@ -10,7 +10,6 @@ using "ui/widgets/widgets.style";
|
|||
using "info/info.style";
|
||||
using "boxes/boxes.style";
|
||||
|
||||
settingsFirstDividerSkip: 3px;
|
||||
settingsSectionButton: InfoProfileButton(infoProfileButton) {
|
||||
font: boxTextFont;
|
||||
padding: margins(79px, 13px, 22px, 11px);
|
||||
|
@ -22,7 +21,7 @@ settingsButton: InfoProfileButton(settingsSectionButton) {
|
|||
padding: margins(22px, 13px, 22px, 11px);
|
||||
}
|
||||
settingsSectionSkip: 9px;
|
||||
settingsSectionIconPosition: point(22px, 9px);
|
||||
settingsSectionIconLeft: 22px;
|
||||
settingsSeparatorPadding: margins(22px, infoProfileSkip, 0px, infoProfileSkip);
|
||||
settingsButtonRightPosition: point(28px, 13px);
|
||||
settingsButtonRight: FlatLabel(defaultFlatLabel) {
|
||||
|
@ -48,7 +47,6 @@ settingsUpdate: InfoProfileButton(infoMainButton, settingsButton) {
|
|||
settingsUpdateStatePosition: point(24px, 29px);
|
||||
settingsDividerLabelPadding: margins(22px, 10px, 22px, 19px);
|
||||
|
||||
settingsIconSetPhoto: icon {{ "settings_set_photo", menuIconFg }};
|
||||
settingsIconInformation: icon {{ "settings_information", menuIconFg }};
|
||||
settingsIconNotifications: icon {{ "settings_notifications", menuIconFg }};
|
||||
settingsIconChat: icon {{ "settings_chat", menuIconFg }};
|
||||
|
@ -68,6 +66,7 @@ settingsLink: boxLinkButton;
|
|||
settingsAdvancedNotificationsPadding: margins(22px, 20px, 10px, 10px);
|
||||
settingsLinkLabel: defaultFlatLabel;
|
||||
settingsCheckboxesSkip: 12px;
|
||||
settingsStickersEmojiPadding: 17px;
|
||||
|
||||
settingsSendType: settingsCheckbox;
|
||||
settingsSendTypePadding: margins(22px, 5px, 10px, 5px);
|
||||
|
@ -100,7 +99,20 @@ settingsCloudPasswordLabel: FlatLabel(defaultFlatLabel) {
|
|||
}
|
||||
settingsCloudPasswordLabelPadding: margins(22px, 8px, 10px, 8px);
|
||||
|
||||
settingsInfoRowHeight: 62px;
|
||||
settingsInfoPhotoHeight: 175px;
|
||||
settingsInfoPhotoSize: 84px;
|
||||
settingsInfoPhoto: UserpicButton(defaultUserpicButton) {
|
||||
size: size(settingsInfoPhotoSize, settingsInfoPhotoSize);
|
||||
photoSize: settingsInfoPhotoSize;
|
||||
}
|
||||
settingsInfoPhotoTop: 17px;
|
||||
settingsInfoPhotoSkip: 16px;
|
||||
settingsInfoPhotoSet: defaultActiveButton;
|
||||
|
||||
settingsInfoRow: InfoProfileButton(settingsButton) {
|
||||
height: 62px;
|
||||
padding: margins(0px, 0px, 0px, 0px);
|
||||
}
|
||||
settingsInfoIconPosition: point(22px, 18px);
|
||||
settingsInfoValue: FlatLabel(defaultFlatLabel) {
|
||||
textFg: windowFg;
|
||||
|
@ -114,24 +126,11 @@ settingsInfoAbout: FlatLabel(settingsInfoValue) {
|
|||
}
|
||||
settingsInfoAboutPosition: point(78px, 34px);
|
||||
settingsInfoRightSkip: 60px;
|
||||
settingsInfoEditPosition: point(0px, 6px);
|
||||
settingsInfoEdit: IconButton(defaultIconButton) {
|
||||
width: 56px;
|
||||
height: 56px;
|
||||
|
||||
icon: icon {{ "settings_edit", menuIconFg }};
|
||||
iconOver: icon {{ "settings_edit", menuIconFgOver }};
|
||||
iconPosition: point(14px, 14px);
|
||||
|
||||
rippleAreaPosition: point(8px, 8px);
|
||||
rippleAreaSize: 40px;
|
||||
ripple: RippleAnimation(defaultRippleAnimation) {
|
||||
color: windowBgOver;
|
||||
}
|
||||
}
|
||||
settingsInfoEditRight: 14px;
|
||||
settingsInfoEditIconOver: icon {{ "settings_edit", menuIconFgOver }};
|
||||
settingsBio: InputField(defaultInputField) {
|
||||
textBg: transparent;
|
||||
textMargins: margins(2px, 7px, 2px, 0px);
|
||||
textMargins: margins(0px, 7px, 0px, 13px);
|
||||
|
||||
placeholderFg: placeholderFg;
|
||||
placeholderFgActive: placeholderFgActive;
|
||||
|
@ -140,9 +139,6 @@ settingsBio: InputField(defaultInputField) {
|
|||
placeholderScale: 0.;
|
||||
placeholderFont: normalFont;
|
||||
|
||||
border: 0px;
|
||||
borderActive: 0px;
|
||||
|
||||
heightMin: 32px;
|
||||
|
||||
font: boxTextFont;
|
||||
|
@ -157,3 +153,4 @@ settingsBioCountdown: FlatLabel(defaultFlatLabel) {
|
|||
style: boxTextStyle;
|
||||
textFg: windowSubTextFg;
|
||||
}
|
||||
settingsBioLabelPadding: margins(22px, 11px, 22px, 0px);
|
||||
|
|
|
@ -369,9 +369,10 @@ void DownloadPathRow::setupControls() {
|
|||
|
||||
#endif // OS_WIN_STORE
|
||||
|
||||
void SetupChatOptions(not_null<Ui::VerticalLayout*> container) {
|
||||
AddDivider(container);
|
||||
AddSkip(container, st::settingsCheckboxesSkip);
|
||||
void SetupStickersEmoji(not_null<Ui::VerticalLayout*> container) {
|
||||
AddSkip(container, st::settingsStickersEmojiPadding);
|
||||
|
||||
AddSubsectionTitle(container, lng_settings_stickers_emoji);
|
||||
|
||||
auto wrap = object_ptr<Ui::VerticalLayout>(container);
|
||||
const auto inner = wrap.data();
|
||||
|
@ -422,65 +423,31 @@ void SetupChatOptions(not_null<Ui::VerticalLayout*> container) {
|
|||
Local::writeUserSettings();
|
||||
});
|
||||
|
||||
const auto dontask = inner->add(
|
||||
checkbox(
|
||||
lng_download_path_dont_ask,
|
||||
!Global::AskDownloadPath()),
|
||||
#ifndef OS_WIN_STORE
|
||||
st::settingsAskPathPadding);
|
||||
#else // OS_WIN_STORE
|
||||
st::settingsCheckboxPadding);
|
||||
#endif // OS_WIN_STORE
|
||||
|
||||
#ifndef OS_WIN_STORE
|
||||
const auto showpath = Ui::AttachAsChild(
|
||||
dontask,
|
||||
rpl::event_stream<bool>());
|
||||
const auto padding = st::settingsDownloadPathPadding;
|
||||
const auto path = container->add(
|
||||
object_ptr<Ui::SlideWrap<DownloadPathRow>>(
|
||||
container,
|
||||
object_ptr<DownloadPathRow>(container),
|
||||
QMargins(
|
||||
(padding.left()
|
||||
+ st::settingsCheckbox.checkPosition.x()
|
||||
+ st::defaultCheck.diameter
|
||||
+ st::settingsCheckbox.textPosition.x()
|
||||
- st::settingsCheckbox.margin.left()),
|
||||
padding.top(),
|
||||
padding.right(),
|
||||
padding.bottom())));
|
||||
AddSkip(container, st::settingsCheckboxPadding.bottom());
|
||||
path->toggleOn(
|
||||
showpath->events_starting_with(!Global::AskDownloadPath()));
|
||||
#endif // OS_WIN_STORE
|
||||
|
||||
base::ObservableViewer(
|
||||
dontask->checkedChanged
|
||||
) | rpl::start_with_next([=](bool checked) {
|
||||
Global::SetAskDownloadPath(!checked);
|
||||
Local::writeUserSettings();
|
||||
|
||||
#ifndef OS_WIN_STORE
|
||||
showpath->fire_copy(checked);
|
||||
#endif // OS_WIN_STORE
|
||||
|
||||
}, inner->lifetime());
|
||||
AddButton(
|
||||
container,
|
||||
lng_stickers_you_have,
|
||||
st::settingsButton
|
||||
)->addClickHandler([] {
|
||||
Ui::show(Box<StickersBox>(StickersBox::Section::Installed));
|
||||
});
|
||||
|
||||
AddSkip(container, st::settingsCheckboxesSkip);
|
||||
}
|
||||
|
||||
void SetupSendKey(not_null<Ui::VerticalLayout*> container) {
|
||||
void SetupChatOther(not_null<Ui::VerticalLayout*> container) {
|
||||
AddDivider(container);
|
||||
const auto skip = st::settingsSendTypeSkip;
|
||||
const auto full = st::settingsCheckboxesSkip + skip;
|
||||
AddSkip(container, full);
|
||||
AddSkip(container, st::settingsSectionSkip);
|
||||
|
||||
AddSubsectionTitle(container, lng_settings_chat_other);
|
||||
|
||||
AddSkip(container, st::settingsSendTypeSkip);
|
||||
|
||||
enum class SendByType {
|
||||
Enter,
|
||||
CtrlEnter,
|
||||
};
|
||||
|
||||
const auto skip = st::settingsSendTypeSkip;
|
||||
const auto group = std::make_shared<Ui::RadioenumGroup<SendByType>>(
|
||||
cCtrlEnter() ? SendByType::CtrlEnter : SendByType::Enter);
|
||||
auto wrap = object_ptr<Ui::VerticalLayout>(container);
|
||||
|
@ -491,8 +458,6 @@ void SetupSendKey(not_null<Ui::VerticalLayout*> container) {
|
|||
std::move(wrap),
|
||||
QMargins(0, skip, 0, skip)));
|
||||
|
||||
AddSkip(container, full);
|
||||
|
||||
const auto add = [&](
|
||||
SendByType value,
|
||||
LangKey key,
|
||||
|
@ -525,11 +490,55 @@ void SetupSendKey(not_null<Ui::VerticalLayout*> container) {
|
|||
}
|
||||
Local::writeUserSettings();
|
||||
});
|
||||
}
|
||||
|
||||
void SetupMediaOptions(not_null<Ui::VerticalLayout*> container) {
|
||||
AddDivider(container);
|
||||
AddSkip(container);
|
||||
AddSkip(inner, st::settingsCheckboxesSkip);
|
||||
|
||||
const auto dontask = inner->add(
|
||||
object_ptr<Ui::Checkbox>(
|
||||
inner,
|
||||
lang(lng_download_path_dont_ask),
|
||||
!Global::AskDownloadPath(),
|
||||
st::settingsCheckbox),
|
||||
#ifndef OS_WIN_STORE
|
||||
st::settingsAskPathPadding);
|
||||
#else // OS_WIN_STORE
|
||||
st::settingsCheckboxPadding);
|
||||
#endif // OS_WIN_STORE
|
||||
|
||||
#ifndef OS_WIN_STORE
|
||||
const auto showpath = Ui::AttachAsChild(
|
||||
dontask,
|
||||
rpl::event_stream<bool>());
|
||||
const auto padding = st::settingsDownloadPathPadding;
|
||||
const auto path = container->add(
|
||||
object_ptr<Ui::SlideWrap<DownloadPathRow>>(
|
||||
container,
|
||||
object_ptr<DownloadPathRow>(container),
|
||||
QMargins(
|
||||
(padding.left()
|
||||
+ st::settingsCheckbox.checkPosition.x()
|
||||
+ st::defaultCheck.diameter
|
||||
+ st::settingsCheckbox.textPosition.x()
|
||||
- st::settingsCheckbox.margin.left()),
|
||||
padding.top(),
|
||||
padding.right(),
|
||||
padding.bottom())));
|
||||
AddSkip(container, st::settingsCheckboxPadding.bottom());
|
||||
path->toggleOn(
|
||||
showpath->events_starting_with(!Global::AskDownloadPath()));
|
||||
#endif // OS_WIN_STORE
|
||||
|
||||
base::ObservableViewer(
|
||||
dontask->checkedChanged
|
||||
) | rpl::start_with_next([=](bool checked) {
|
||||
Global::SetAskDownloadPath(!checked);
|
||||
Local::writeUserSettings();
|
||||
|
||||
#ifndef OS_WIN_STORE
|
||||
showpath->fire_copy(checked);
|
||||
#endif // OS_WIN_STORE
|
||||
|
||||
}, inner->lifetime());
|
||||
|
||||
AddButton(
|
||||
container,
|
||||
|
@ -539,20 +548,12 @@ void SetupMediaOptions(not_null<Ui::VerticalLayout*> container) {
|
|||
Ui::show(Box<AutoDownloadBox>());
|
||||
});
|
||||
|
||||
AddButton(
|
||||
container,
|
||||
lng_stickers_you_have,
|
||||
st::settingsButton
|
||||
)->addClickHandler([] {
|
||||
Ui::show(Box<StickersBox>(StickersBox::Section::Installed));
|
||||
});
|
||||
|
||||
AddSkip(container);
|
||||
AddSkip(container, st::settingsCheckboxesSkip);
|
||||
}
|
||||
|
||||
void SetupChatBackground(not_null<Ui::VerticalLayout*> container) {
|
||||
AddDivider(container);
|
||||
AddSkip(container, st::settingsCheckboxesSkip);
|
||||
AddSkip(container, st::settingsSectionSkip);
|
||||
|
||||
AddSubsectionTitle(container, lng_settings_section_background);
|
||||
|
||||
|
@ -673,6 +674,8 @@ void SetupThemeOptions(not_null<Ui::VerticalLayout*> container) {
|
|||
AddDivider(container);
|
||||
AddSkip(container);
|
||||
|
||||
AddSubsectionTitle(container, lng_settings_themes);
|
||||
|
||||
SetupNightMode(container);
|
||||
|
||||
AddButton(
|
||||
|
@ -698,12 +701,10 @@ Chat::Chat(QWidget *parent, not_null<UserData*> self)
|
|||
void Chat::setupContent() {
|
||||
const auto content = Ui::CreateChild<Ui::VerticalLayout>(this);
|
||||
|
||||
AddSkip(content, st::settingsFirstDividerSkip);
|
||||
SetupChatOptions(content);
|
||||
SetupSendKey(content);
|
||||
SetupMediaOptions(content);
|
||||
SetupStickersEmoji(content);
|
||||
SetupChatBackground(content);
|
||||
SetupThemeOptions(content);
|
||||
SetupChatOther(content);
|
||||
|
||||
Ui::ResizeFitChild(this, content);
|
||||
}
|
||||
|
|
|
@ -32,17 +32,17 @@ object_ptr<Section> CreateSection(
|
|||
UserData *self) {
|
||||
switch (type) {
|
||||
case Type::Main:
|
||||
return object_ptr<::Settings::Main>(parent, controller, self);
|
||||
return object_ptr<Main>(parent, controller, self);
|
||||
case Type::Information:
|
||||
return object_ptr<::Settings::Information>(parent, self);
|
||||
return object_ptr<Information>(parent, controller, self);
|
||||
case Type::Notifications:
|
||||
return object_ptr<::Settings::Notifications>(parent, self);
|
||||
return object_ptr<Notifications>(parent, self);
|
||||
case Type::PrivacySecurity:
|
||||
return object_ptr<::Settings::PrivacySecurity>(parent, self);
|
||||
return object_ptr<PrivacySecurity>(parent, self);
|
||||
case Type::General:
|
||||
return object_ptr<::Settings::General>(parent, self);
|
||||
return object_ptr<General>(parent, self);
|
||||
case Type::Chat:
|
||||
return object_ptr<::Settings::Chat>(parent, self);
|
||||
return object_ptr<Chat>(parent, self);
|
||||
}
|
||||
Unexpected("Settings section type in Widget::createInnerWidget.");
|
||||
}
|
||||
|
@ -78,26 +78,36 @@ not_null<Button*> AddButton(
|
|||
LangKey text,
|
||||
const style::InfoProfileButton &st,
|
||||
const style::icon *leftIcon) {
|
||||
return AddButton(container, Lang::Viewer(text), st, leftIcon);
|
||||
}
|
||||
|
||||
not_null<Button*> AddButton(
|
||||
not_null<Ui::VerticalLayout*> container,
|
||||
rpl::producer<QString> text,
|
||||
const style::InfoProfileButton &st,
|
||||
const style::icon *leftIcon) {
|
||||
const auto result = container->add(object_ptr<Button>(
|
||||
container,
|
||||
Lang::Viewer(text),
|
||||
std::move(text),
|
||||
st));
|
||||
if (leftIcon) {
|
||||
const auto icon = Ui::CreateChild<Ui::RpWidget>(result);
|
||||
icon->setAttribute(Qt::WA_TransparentForMouseEvents);
|
||||
icon->resize(leftIcon->size());
|
||||
result->widthValue(
|
||||
) | rpl::start_with_next([=](int width) {
|
||||
result->sizeValue(
|
||||
) | rpl::start_with_next([=](QSize size) {
|
||||
icon->moveToLeft(
|
||||
st::settingsSectionIconPosition.x(),
|
||||
st::settingsSectionIconPosition.y(),
|
||||
width);
|
||||
st::settingsSectionIconLeft,
|
||||
(size.height() - icon->height()) / 2,
|
||||
size.width());
|
||||
}, icon->lifetime());
|
||||
icon->paintRequest(
|
||||
) | rpl::start_with_next([=] {
|
||||
Painter p(icon);
|
||||
const auto width = icon->width();
|
||||
if (result->isOver()) {
|
||||
const auto paintOver = (result->isOver() || result->isDown())
|
||||
&& !result->isDisabled();
|
||||
if (paintOver) {
|
||||
leftIcon->paint(p, QPoint(), width, st::menuIconFgOver->c);
|
||||
} else {
|
||||
leftIcon->paint(p, QPoint(), width);
|
||||
|
|
|
@ -75,6 +75,11 @@ not_null<Button*> AddButton(
|
|||
LangKey text,
|
||||
const style::InfoProfileButton &st,
|
||||
const style::icon *leftIcon = nullptr);
|
||||
not_null<Button*> AddButton(
|
||||
not_null<Ui::VerticalLayout*> container,
|
||||
rpl::producer<QString> text,
|
||||
const style::InfoProfileButton &st,
|
||||
const style::icon *leftIcon = nullptr);
|
||||
not_null<Button*> AddButtonWithLabel(
|
||||
not_null<Ui::VerticalLayout*> container,
|
||||
LangKey text,
|
||||
|
|
|
@ -11,6 +11,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "ui/wrap/vertical_layout.h"
|
||||
#include "ui/wrap/slide_wrap.h"
|
||||
#include "ui/widgets/labels.h"
|
||||
#include "ui/widgets/checkbox.h"
|
||||
#include "boxes/local_storage_box.h"
|
||||
#include "boxes/connection_box.h"
|
||||
#include "boxes/about_box.h"
|
||||
|
@ -68,7 +69,6 @@ void SetupConnectionType(not_null<Ui::VerticalLayout*> container) {
|
|||
}
|
||||
|
||||
void SetupStorageAndConnection(not_null<Ui::VerticalLayout*> container) {
|
||||
AddDivider(container);
|
||||
AddSkip(container);
|
||||
|
||||
AddButton(
|
||||
|
@ -230,44 +230,50 @@ bool HasTray() {
|
|||
return cSupportTray() || (cPlatform() == dbipWindows);
|
||||
}
|
||||
|
||||
void SetupTray(not_null<Ui::VerticalLayout*> container) {
|
||||
if (!HasTray()) {
|
||||
return;
|
||||
}
|
||||
void SetupTrayContent(not_null<Ui::VerticalLayout*> container) {
|
||||
const auto checkbox = [&](LangKey label, bool checked) {
|
||||
return object_ptr<Ui::Checkbox>(
|
||||
container,
|
||||
lang(label),
|
||||
checked,
|
||||
st::settingsCheckbox);
|
||||
};
|
||||
const auto addCheckbox = [&](LangKey label, bool checked) {
|
||||
return container->add(
|
||||
checkbox(label, checked),
|
||||
st::settingsCheckboxPadding);
|
||||
};
|
||||
const auto addSlidingCheckbox = [&](LangKey label, bool checked) {
|
||||
return container->add(
|
||||
object_ptr<Ui::SlideWrap<Ui::Checkbox>>(
|
||||
container,
|
||||
checkbox(label, checked),
|
||||
st::settingsCheckboxPadding));
|
||||
};
|
||||
|
||||
const auto trayEnabler = Ui::AttachAsChild(
|
||||
container,
|
||||
rpl::event_stream<bool>());
|
||||
const auto trayEnabled = [] {
|
||||
const auto workMode = Global::WorkMode().value();
|
||||
return (workMode == dbiwmTrayOnly)
|
||||
|| (workMode == dbiwmWindowAndTray);
|
||||
};
|
||||
const auto tray = AddButton(
|
||||
container,
|
||||
const auto tray = addCheckbox(
|
||||
lng_settings_workmode_tray,
|
||||
st::settingsGeneralButton
|
||||
)->toggleOn(trayEnabler->events_starting_with(trayEnabled()));
|
||||
trayEnabled());
|
||||
|
||||
const auto taskbarEnabled = [] {
|
||||
const auto workMode = Global::WorkMode().value();
|
||||
return (workMode == dbiwmWindowOnly)
|
||||
|| (workMode == dbiwmWindowAndTray);
|
||||
};
|
||||
const auto taskbarEnabler = Ui::AttachAsChild(
|
||||
container,
|
||||
rpl::event_stream<bool>());
|
||||
const auto taskbar = (cPlatform() == dbipWindows)
|
||||
? AddButton(
|
||||
container,
|
||||
? addCheckbox(
|
||||
lng_settings_workmode_window,
|
||||
st::settingsGeneralButton
|
||||
)->toggleOn(taskbarEnabler->events_starting_with(taskbarEnabled()))
|
||||
taskbarEnabled())
|
||||
: nullptr;
|
||||
|
||||
const auto updateWorkmode = [=] {
|
||||
const auto newMode = tray->toggled()
|
||||
? ((!taskbar || taskbar->toggled())
|
||||
const auto newMode = tray->checked()
|
||||
? ((!taskbar || taskbar->checked())
|
||||
? dbiwmWindowAndTray
|
||||
: dbiwmTrayOnly)
|
||||
: dbiwmWindowOnly;
|
||||
|
@ -279,24 +285,26 @@ void SetupTray(not_null<Ui::VerticalLayout*> container) {
|
|||
Local::writeSettings();
|
||||
};
|
||||
|
||||
tray->toggledValue(
|
||||
base::ObservableViewer(
|
||||
tray->checkedChanged
|
||||
) | rpl::filter([=](bool checked) {
|
||||
return (checked != trayEnabled());
|
||||
}) | rpl::start_with_next([=](bool checked) {
|
||||
if (!checked && taskbar && !taskbar->toggled()) {
|
||||
taskbarEnabler->fire(true);
|
||||
if (!checked && taskbar && !taskbar->checked()) {
|
||||
taskbar->setChecked(true);
|
||||
} else {
|
||||
updateWorkmode();
|
||||
}
|
||||
}, tray->lifetime());
|
||||
|
||||
if (taskbar) {
|
||||
taskbar->toggledValue(
|
||||
base::ObservableViewer(
|
||||
taskbar->checkedChanged
|
||||
) | rpl::filter([=](bool checked) {
|
||||
return (checked != taskbarEnabled());
|
||||
}) | rpl::start_with_next([=](bool checked) {
|
||||
if (!checked && !tray->toggled()) {
|
||||
trayEnabler->fire(true);
|
||||
if (!checked && !tray->checked()) {
|
||||
tray->setChecked(true);
|
||||
} else {
|
||||
updateWorkmode();
|
||||
}
|
||||
|
@ -305,32 +313,22 @@ void SetupTray(not_null<Ui::VerticalLayout*> container) {
|
|||
|
||||
#ifndef OS_WIN_STORE
|
||||
if (cPlatform() == dbipWindows) {
|
||||
const auto autostart = AddButton(
|
||||
container,
|
||||
lng_settings_auto_start,
|
||||
st::settingsGeneralButton
|
||||
)->toggleOn(rpl::single(cAutoStart()));
|
||||
const auto minimized = container->add(
|
||||
object_ptr<Ui::SlideWrap<Button>>(
|
||||
container,
|
||||
object_ptr<Button>(
|
||||
container,
|
||||
Lang::Viewer(lng_settings_start_min),
|
||||
st::settingsGeneralButton)));
|
||||
const auto sendto = AddButton(
|
||||
container,
|
||||
lng_settings_add_sendto,
|
||||
st::settingsGeneralButton
|
||||
)->toggleOn(rpl::single(cSendToMenu()));
|
||||
|
||||
const auto minimizedToggler = Ui::AttachAsChild(
|
||||
minimized,
|
||||
rpl::event_stream<bool>());
|
||||
const auto minimizedToggled = [] {
|
||||
return cStartMinimized() && !Global::LocalPasscode();
|
||||
};
|
||||
|
||||
autostart->toggledValue(
|
||||
const auto autostart = addCheckbox(
|
||||
lng_settings_auto_start,
|
||||
cAutoStart());
|
||||
const auto minimized = addSlidingCheckbox(
|
||||
lng_settings_start_min,
|
||||
minimizedToggled());
|
||||
const auto sendto = addCheckbox(
|
||||
lng_settings_add_sendto,
|
||||
cSendToMenu());
|
||||
|
||||
base::ObservableViewer(
|
||||
autostart->checkedChanged
|
||||
) | rpl::filter([](bool checked) {
|
||||
return (checked != cAutoStart());
|
||||
}) | rpl::start_with_next([=](bool checked) {
|
||||
|
@ -338,22 +336,25 @@ void SetupTray(not_null<Ui::VerticalLayout*> container) {
|
|||
psAutoStart(checked);
|
||||
if (checked) {
|
||||
Local::writeSettings();
|
||||
} else if (minimized->entity()->toggled()) {
|
||||
minimizedToggler->fire(false);
|
||||
} else if (minimized->entity()->checked()) {
|
||||
minimized->entity()->setChecked(false);
|
||||
} else {
|
||||
Local::writeSettings();
|
||||
}
|
||||
}, autostart->lifetime());
|
||||
|
||||
minimized->entity()->toggleOn(
|
||||
minimizedToggler->events_starting_with(minimizedToggled()));
|
||||
minimized->toggleOn(autostart->toggledValue());
|
||||
minimized->entity()->toggledValue(
|
||||
minimized->toggleOn(rpl::single(
|
||||
autostart->checked()
|
||||
) | rpl::then(base::ObservableViewer(
|
||||
autostart->checkedChanged
|
||||
)));
|
||||
base::ObservableViewer(
|
||||
minimized->entity()->checkedChanged
|
||||
) | rpl::filter([=](bool checked) {
|
||||
return (checked != minimizedToggled());
|
||||
}) | rpl::start_with_next([=](bool checked) {
|
||||
if (Global::LocalPasscode()) {
|
||||
minimizedToggler->fire(false);
|
||||
minimized->entity()->setChecked(false);
|
||||
Ui::show(Box<InformBox>(
|
||||
lang(lng_error_start_minimized_passcoded)));
|
||||
} else {
|
||||
|
@ -365,10 +366,11 @@ void SetupTray(not_null<Ui::VerticalLayout*> container) {
|
|||
base::ObservableViewer(
|
||||
Global::RefLocalPasscodeChanged()
|
||||
) | rpl::start_with_next([=] {
|
||||
minimizedToggler->fire(minimizedToggled());
|
||||
minimized->entity()->setChecked(minimizedToggled());
|
||||
}, minimized->lifetime());
|
||||
|
||||
sendto->toggledValue(
|
||||
base::ObservableViewer(
|
||||
sendto->checkedChanged
|
||||
) | rpl::filter([](bool checked) {
|
||||
return (checked != cSendToMenu());
|
||||
}) | rpl::start_with_next([](bool checked) {
|
||||
|
@ -380,6 +382,21 @@ void SetupTray(not_null<Ui::VerticalLayout*> container) {
|
|||
#endif // OS_WIN_STORE
|
||||
}
|
||||
|
||||
void SetupTray(not_null<Ui::VerticalLayout*> container) {
|
||||
if (!HasTray()) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto wrap = object_ptr<Ui::VerticalLayout>(container);
|
||||
SetupTrayContent(wrap.data());
|
||||
|
||||
container->add(object_ptr<Ui::OverrideMargins>(
|
||||
container,
|
||||
std::move(wrap)));
|
||||
|
||||
AddSkip(container, st::settingsCheckboxesSkip);
|
||||
}
|
||||
|
||||
General::General(QWidget *parent, UserData *self)
|
||||
: Section(parent) {
|
||||
setupContent();
|
||||
|
@ -388,21 +405,21 @@ General::General(QWidget *parent, UserData *self)
|
|||
void General::setupContent() {
|
||||
const auto content = Ui::CreateChild<Ui::VerticalLayout>(this);
|
||||
|
||||
AddSkip(content, st::settingsFirstDividerSkip);
|
||||
|
||||
if (!Core::UpdaterDisabled()) {
|
||||
AddDivider(content);
|
||||
AddSkip(content);
|
||||
SetupUpdate(content);
|
||||
AddSkip(content);
|
||||
}
|
||||
if (!Core::UpdaterDisabled()) {
|
||||
AddDivider(content);
|
||||
}
|
||||
SetupStorageAndConnection(content);
|
||||
if (HasTray()) {
|
||||
AddDivider(content);
|
||||
AddSkip(content);
|
||||
SetupTray(content);
|
||||
AddSkip(content);
|
||||
}
|
||||
SetupStorageAndConnection(content);
|
||||
|
||||
Ui::ResizeFitChild(this, content);
|
||||
}
|
||||
|
|
|
@ -13,34 +13,127 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "ui/widgets/labels.h"
|
||||
#include "ui/widgets/buttons.h"
|
||||
#include "ui/widgets/input_fields.h"
|
||||
#include "ui/widgets/popup_menu.h"
|
||||
#include "ui/special_buttons.h"
|
||||
#include "boxes/add_contact_box.h"
|
||||
#include "boxes/confirm_box.h"
|
||||
#include "boxes/change_phone_box.h"
|
||||
#include "boxes/photo_crop_box.h"
|
||||
#include "boxes/username_box.h"
|
||||
#include "info/profile/info_profile_values.h"
|
||||
#include "info/profile/info_profile_button.h"
|
||||
#include "lang/lang_keys.h"
|
||||
#include "auth_session.h"
|
||||
#include "apiwrap.h"
|
||||
#include "core/file_utilities.h"
|
||||
#include "styles/style_boxes.h"
|
||||
#include "styles/style_settings.h"
|
||||
|
||||
namespace Settings {
|
||||
namespace {
|
||||
|
||||
void SetupPhoto(
|
||||
not_null<Ui::VerticalLayout*> container,
|
||||
not_null<Window::Controller*> controller,
|
||||
not_null<UserData*> self) {
|
||||
const auto wrap = container->add(object_ptr<BoxContentDivider>(
|
||||
container,
|
||||
st::settingsInfoPhotoHeight));
|
||||
const auto photo = Ui::CreateChild<Ui::UserpicButton>(
|
||||
wrap,
|
||||
controller,
|
||||
self,
|
||||
Ui::UserpicButton::Role::OpenPhoto,
|
||||
st::settingsInfoPhoto);
|
||||
const auto upload = Ui::CreateChild<Ui::RoundButton>(
|
||||
wrap,
|
||||
langFactory(lng_settings_upload),
|
||||
st::settingsInfoPhotoSet);
|
||||
upload->setFullRadius(true);
|
||||
upload->addClickHandler([=] {
|
||||
const auto imageExtensions = cImgExtensions();
|
||||
const auto filter = qsl("Image files (*")
|
||||
+ imageExtensions.join(qsl(" *"))
|
||||
+ qsl(");;")
|
||||
+ FileDialog::AllFilesFilter();
|
||||
const auto callback = [=](const FileDialog::OpenResult &result) {
|
||||
if (result.paths.isEmpty() && result.remoteContent.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
const auto image = result.remoteContent.isEmpty()
|
||||
? App::readImage(result.paths.front())
|
||||
: App::readImage(result.remoteContent);
|
||||
if (image.isNull()
|
||||
|| image.width() > 10 * image.height()
|
||||
|| image.height() > 10 * image.width()) {
|
||||
Ui::show(Box<InformBox>(lang(lng_bad_photo)));
|
||||
return;
|
||||
}
|
||||
|
||||
auto box = Ui::show(Box<PhotoCropBox>(image, self));
|
||||
box->ready(
|
||||
) | rpl::start_with_next([=](QImage &&image) {
|
||||
Auth().api().uploadPeerPhoto(self, std::move(image));
|
||||
}, box->lifetime());
|
||||
};
|
||||
FileDialog::GetOpenPath(
|
||||
upload,
|
||||
lang(lng_choose_image),
|
||||
filter,
|
||||
crl::guard(upload, callback));
|
||||
});
|
||||
rpl::combine(
|
||||
wrap->widthValue(),
|
||||
photo->widthValue(),
|
||||
upload->widthValue()
|
||||
) | rpl::start_with_next([=](int max, int photoWidth, int uploadWidth) {
|
||||
photo->moveToLeft(
|
||||
(max - photoWidth) / 2,
|
||||
st::settingsInfoPhotoTop);
|
||||
upload->moveToLeft(
|
||||
(max - uploadWidth) / 2,
|
||||
(st::settingsInfoPhotoTop
|
||||
+ photo->height()
|
||||
+ st::settingsInfoPhotoSkip));
|
||||
}, photo->lifetime());
|
||||
}
|
||||
|
||||
void ShowMenu(
|
||||
QWidget *parent,
|
||||
const QString ©Button,
|
||||
const QString &text) {
|
||||
const auto menu = new Ui::PopupMenu(parent);
|
||||
|
||||
menu->addAction(copyButton, [=] {
|
||||
QApplication::clipboard()->setText(text);
|
||||
});
|
||||
menu->popup(QCursor::pos());
|
||||
}
|
||||
|
||||
void AddRow(
|
||||
not_null<Ui::VerticalLayout*> container,
|
||||
rpl::producer<QString> label,
|
||||
rpl::producer<TextWithEntities> value,
|
||||
const QString ©Text,
|
||||
const style::IconButton &editSt,
|
||||
const QString ©Button,
|
||||
Fn<void()> edit,
|
||||
const style::icon &icon) {
|
||||
const auto wrap = container->add(object_ptr<Ui::FixedHeightWidget>(
|
||||
const auto wrap = AddButton(
|
||||
container,
|
||||
st::settingsInfoRowHeight));
|
||||
|
||||
wrap->paintRequest(
|
||||
) | rpl::start_with_next([=, &icon] {
|
||||
Painter p(wrap);
|
||||
icon.paint(p, st::settingsInfoIconPosition, wrap->width());
|
||||
rpl::single(QString()),
|
||||
st::settingsInfoRow,
|
||||
&icon);
|
||||
const auto forcopy = Ui::AttachAsChild(wrap, QString());
|
||||
wrap->setAcceptBoth();
|
||||
wrap->clicks(
|
||||
) | rpl::filter([=] {
|
||||
return !wrap->isDisabled();
|
||||
}) | rpl::start_with_next([=](Qt::MouseButton button) {
|
||||
if (button == Qt::LeftButton) {
|
||||
edit();
|
||||
} else if (!forcopy->isEmpty()) {
|
||||
ShowMenu(wrap, copyButton, *forcopy);
|
||||
}
|
||||
}, wrap->lifetime());
|
||||
|
||||
auto existing = base::duplicate(
|
||||
|
@ -48,8 +141,15 @@ void AddRow(
|
|||
) | rpl::map([](const TextWithEntities &text) {
|
||||
return text.entities.isEmpty();
|
||||
});
|
||||
base::duplicate(
|
||||
value
|
||||
) | rpl::filter([](const TextWithEntities &text) {
|
||||
return text.entities.isEmpty();
|
||||
}) | rpl::start_with_next([=](const TextWithEntities &text) {
|
||||
*forcopy = text.text;
|
||||
}, wrap->lifetime());
|
||||
const auto text = Ui::CreateChild<Ui::FlatLabel>(
|
||||
wrap,
|
||||
wrap.get(),
|
||||
std::move(value),
|
||||
st::settingsInfoValue);
|
||||
text->setClickHandlerFilter([=](auto&&...) {
|
||||
|
@ -59,24 +159,32 @@ void AddRow(
|
|||
base::duplicate(
|
||||
existing
|
||||
) | rpl::start_with_next([=](bool existing) {
|
||||
wrap->setDisabled(!existing);
|
||||
text->setAttribute(Qt::WA_TransparentForMouseEvents, existing);
|
||||
text->setSelectable(existing);
|
||||
text->setDoubleClickSelectsParagraph(existing);
|
||||
text->setContextCopyText(existing ? copyText : QString());
|
||||
}, text->lifetime());
|
||||
|
||||
const auto about = Ui::CreateChild<Ui::FlatLabel>(
|
||||
wrap,
|
||||
wrap.get(),
|
||||
std::move(label),
|
||||
st::settingsInfoAbout);
|
||||
about->setAttribute(Qt::WA_TransparentForMouseEvents);
|
||||
|
||||
const auto button = Ui::CreateChild<Ui::IconButton>(
|
||||
wrap,
|
||||
editSt);
|
||||
button->addClickHandler(edit);
|
||||
button->showOn(std::move(existing));
|
||||
const auto button = Ui::CreateChild<Ui::RpWidget>(wrap.get());
|
||||
button->resize(st::settingsInfoEditIconOver.size());
|
||||
button->setAttribute(Qt::WA_TransparentForMouseEvents);
|
||||
button->paintRequest(
|
||||
) | rpl::filter([=] {
|
||||
return (wrap->isOver() || wrap->isDown()) && !wrap->isDisabled();
|
||||
}) | rpl::start_with_next([=](QRect clip) {
|
||||
Painter p(button);
|
||||
st::settingsInfoEditIconOver.paint(p, QPoint(), button->width());
|
||||
}, button->lifetime());
|
||||
|
||||
wrap->widthValue(
|
||||
) | rpl::start_with_next([=](int width) {
|
||||
wrap->sizeValue(
|
||||
) | rpl::start_with_next([=](QSize size) {
|
||||
const auto width = size.width();
|
||||
text->resizeToWidth(width
|
||||
- st::settingsInfoValuePosition.x()
|
||||
- st::settingsInfoRightSkip);
|
||||
|
@ -92,8 +200,8 @@ void AddRow(
|
|||
st::settingsInfoAboutPosition.y(),
|
||||
width);
|
||||
button->moveToRight(
|
||||
st::settingsInfoEditPosition.x(),
|
||||
st::settingsInfoEditPosition.y(),
|
||||
st::settingsInfoEditRight,
|
||||
(size.height() - button->height()) / 2,
|
||||
width);
|
||||
}, wrap->lifetime());
|
||||
}
|
||||
|
@ -101,7 +209,6 @@ void AddRow(
|
|||
void SetupRows(
|
||||
not_null<Ui::VerticalLayout*> container,
|
||||
not_null<UserData*> self) {
|
||||
AddDivider(container);
|
||||
AddSkip(container);
|
||||
|
||||
AddRow(
|
||||
|
@ -109,7 +216,6 @@ void SetupRows(
|
|||
Lang::Viewer(lng_settings_name_label),
|
||||
Info::Profile::NameValue(self),
|
||||
lang(lng_profile_copy_fullname),
|
||||
st::settingsInfoEdit,
|
||||
[=] { Ui::show(Box<EditNameBox>(self)); },
|
||||
st::settingsInfoName);
|
||||
|
||||
|
@ -118,7 +224,6 @@ void SetupRows(
|
|||
Lang::Viewer(lng_settings_phone_label),
|
||||
Info::Profile::PhoneValue(self),
|
||||
lang(lng_profile_copy_phone),
|
||||
st::settingsInfoEdit,
|
||||
[] { Ui::show(Box<ChangePhoneBox>()); },
|
||||
st::settingsInfoPhone);
|
||||
|
||||
|
@ -154,7 +259,6 @@ void SetupRows(
|
|||
std::move(label),
|
||||
std::move(value),
|
||||
lang(lng_context_copy_mention),
|
||||
st::settingsInfoEdit,
|
||||
[=] { Ui::show(Box<UsernameBox>()); },
|
||||
st::settingsInfoUsername);
|
||||
|
||||
|
@ -257,8 +361,14 @@ BioManager SetupBio(
|
|||
bio->setInstantReplacesEnabled(Global::ReplaceEmojiValue());
|
||||
updated();
|
||||
|
||||
container->add(
|
||||
object_ptr<Ui::FlatLabel>(
|
||||
container,
|
||||
Lang::Viewer(lng_settings_about_bio),
|
||||
st::boxDividerLabel),
|
||||
st::settingsBioLabelPadding);
|
||||
|
||||
AddSkip(container);
|
||||
AddDividerText(container, Lang::Viewer(lng_settings_about_bio));
|
||||
|
||||
return BioManager{
|
||||
changed->events() | rpl::distinct_until_changed(),
|
||||
|
@ -268,10 +378,13 @@ BioManager SetupBio(
|
|||
|
||||
} // namespace
|
||||
|
||||
Information::Information(QWidget *parent, not_null<UserData*> self)
|
||||
Information::Information(
|
||||
QWidget *parent,
|
||||
not_null<Window::Controller*> controller,
|
||||
not_null<UserData*> self)
|
||||
: Section(parent)
|
||||
, _self(self) {
|
||||
setupContent();
|
||||
setupContent(controller);
|
||||
}
|
||||
|
||||
rpl::producer<bool> Information::sectionCanSaveChanges() {
|
||||
|
@ -282,10 +395,10 @@ void Information::sectionSaveChanges(FnMut<void()> done) {
|
|||
_save(std::move(done));
|
||||
}
|
||||
|
||||
void Information::setupContent() {
|
||||
void Information::setupContent(not_null<Window::Controller*> controller) {
|
||||
const auto content = Ui::CreateChild<Ui::VerticalLayout>(this);
|
||||
|
||||
AddSkip(content, st::settingsFirstDividerSkip);
|
||||
SetupPhoto(content, controller, _self);
|
||||
SetupRows(content, _self);
|
||||
auto manager = SetupBio(content, _self);
|
||||
_canSaveChanges = std::move(manager.canSave);
|
||||
|
|
|
@ -13,13 +13,16 @@ namespace Settings {
|
|||
|
||||
class Information : public Section {
|
||||
public:
|
||||
Information(QWidget *parent, not_null<UserData*> self);
|
||||
Information(
|
||||
QWidget *parent,
|
||||
not_null<Window::Controller*> controller,
|
||||
not_null<UserData*> self);
|
||||
|
||||
rpl::producer<bool> sectionCanSaveChanges() override;
|
||||
void sectionSaveChanges(FnMut<void()> done) override;
|
||||
|
||||
private:
|
||||
void setupContent();
|
||||
void setupContent(not_null<Window::Controller*> controller);
|
||||
|
||||
not_null<UserData*> _self;
|
||||
rpl::variable<bool> _canSaveChanges;
|
||||
|
|
|
@ -12,7 +12,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "boxes/language_box.h"
|
||||
#include "boxes/confirm_box.h"
|
||||
#include "boxes/about_box.h"
|
||||
#include "boxes/photo_crop_box.h"
|
||||
#include "ui/wrap/vertical_layout.h"
|
||||
#include "ui/widgets/labels.h"
|
||||
#include "ui/widgets/discrete_sliders.h"
|
||||
|
@ -27,58 +26,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
|
||||
namespace Settings {
|
||||
|
||||
void SetupUploadPhotoButton(
|
||||
not_null<Ui::VerticalLayout*> container,
|
||||
not_null<UserData*> self) {
|
||||
AddDivider(container);
|
||||
AddSkip(container, st::settingsSetPhotoSkip);
|
||||
|
||||
const auto upload = [=] {
|
||||
const auto imageExtensions = cImgExtensions();
|
||||
const auto filter = qsl("Image files (*")
|
||||
+ imageExtensions.join(qsl(" *"))
|
||||
+ qsl(");;")
|
||||
+ FileDialog::AllFilesFilter();
|
||||
const auto callback = [=](const FileDialog::OpenResult &result) {
|
||||
if (result.paths.isEmpty() && result.remoteContent.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
const auto image = result.remoteContent.isEmpty()
|
||||
? App::readImage(result.paths.front())
|
||||
: App::readImage(result.remoteContent);
|
||||
if (image.isNull()
|
||||
|| image.width() > 10 * image.height()
|
||||
|| image.height() > 10 * image.width()) {
|
||||
Ui::show(Box<InformBox>(lang(lng_bad_photo)));
|
||||
return;
|
||||
}
|
||||
|
||||
auto box = Ui::show(Box<PhotoCropBox>(image, self));
|
||||
box->ready(
|
||||
) | rpl::start_with_next([=](QImage &&image) {
|
||||
Auth().api().uploadPeerPhoto(self, std::move(image));
|
||||
}, box->lifetime());
|
||||
};
|
||||
FileDialog::GetOpenPath(
|
||||
container.get(),
|
||||
lang(lng_choose_image),
|
||||
filter,
|
||||
crl::guard(container, callback));
|
||||
};
|
||||
AddButton(
|
||||
container,
|
||||
lng_settings_upload,
|
||||
st::settingsSectionButton,
|
||||
&st::settingsIconSetPhoto
|
||||
)->addClickHandler(App::LambdaDelayed(
|
||||
st::settingsSectionButton.ripple.hideDuration,
|
||||
container,
|
||||
upload));
|
||||
|
||||
AddSkip(container, st::settingsSetPhotoSkip);
|
||||
}
|
||||
|
||||
void SetupLanguageButton(not_null<Ui::VerticalLayout*> container) {
|
||||
const auto button = AddButtonWithLabel(
|
||||
container,
|
||||
|
@ -121,14 +68,14 @@ void SetupSections(
|
|||
lng_settings_section_privacy,
|
||||
Type::PrivacySecurity,
|
||||
&st::settingsIconPrivacySecurity);
|
||||
addSection(
|
||||
lng_settings_section_general,
|
||||
Type::General,
|
||||
&st::settingsIconGeneral);
|
||||
addSection(
|
||||
lng_settings_section_chat_settings,
|
||||
Type::Chat,
|
||||
&st::settingsIconChat);
|
||||
addSection(
|
||||
lng_settings_advanced,
|
||||
Type::General,
|
||||
&st::settingsIconGeneral);
|
||||
|
||||
SetupLanguageButton(container);
|
||||
|
||||
|
@ -309,7 +256,6 @@ void Main::setupContent(not_null<Window::Controller*> controller) {
|
|||
controller));
|
||||
cover->setOnlineCount(rpl::single(0));
|
||||
|
||||
SetupUploadPhotoButton(content, _self);
|
||||
SetupSections(content, [=](Type type) {
|
||||
_showOther.fire_copy(type);
|
||||
});
|
||||
|
|
|
@ -13,6 +13,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "ui/widgets/checkbox.h"
|
||||
#include "ui/widgets/buttons.h"
|
||||
#include "lang/lang_keys.h"
|
||||
#include "info/profile/info_profile_button.h"
|
||||
#include "storage/localstorage.h"
|
||||
#include "window/notifications_manager.h"
|
||||
#include "boxes/notifications_box.h"
|
||||
|
@ -74,15 +75,26 @@ void SetupNotificationsContent(not_null<Ui::VerticalLayout*> container) {
|
|||
const auto native = nativeNotificationsKey
|
||||
? addCheckbox(nativeNotificationsKey, Global::NativeNotifications())
|
||||
: nullptr;
|
||||
const auto advanced = (cPlatform() != dbipMac)
|
||||
|
||||
const auto advancedSlide = (cPlatform() != dbipMac)
|
||||
? container->add(
|
||||
object_ptr<Ui::SlideWrap<Ui::LinkButton>>(
|
||||
object_ptr<Ui::SlideWrap<Ui::VerticalLayout>>(
|
||||
container,
|
||||
object_ptr<Ui::LinkButton>(
|
||||
container,
|
||||
lang(lng_settings_advanced_notifications),
|
||||
st::settingsLink),
|
||||
st::settingsAdvancedNotificationsPadding))
|
||||
object_ptr<Ui::VerticalLayout>(container)))
|
||||
: nullptr;
|
||||
const auto advancedWrap = advancedSlide
|
||||
? advancedSlide->entity()
|
||||
: nullptr;
|
||||
if (advancedWrap) {
|
||||
AddSkip(advancedWrap, st::settingsCheckboxesSkip);
|
||||
AddDivider(advancedWrap);
|
||||
AddSkip(advancedWrap, st::settingsCheckboxesSkip);
|
||||
}
|
||||
const auto advanced = advancedWrap
|
||||
? AddButton(
|
||||
advancedWrap,
|
||||
lng_settings_advanced_notifications,
|
||||
st::settingsButton).get()
|
||||
: nullptr;
|
||||
|
||||
if (!name->entity()->checked()) {
|
||||
|
@ -92,8 +104,8 @@ void SetupNotificationsContent(not_null<Ui::VerticalLayout*> container) {
|
|||
name->hide(anim::type::instant);
|
||||
preview->hide(anim::type::instant);
|
||||
}
|
||||
if (native && advanced && Global::NativeNotifications()) {
|
||||
advanced->hide(anim::type::instant);
|
||||
if (native && advancedSlide && Global::NativeNotifications()) {
|
||||
advancedSlide->hide(anim::type::instant);
|
||||
}
|
||||
|
||||
using Change = Window::Notifications::ChangeType;
|
||||
|
@ -187,22 +199,21 @@ void SetupNotificationsContent(not_null<Ui::VerticalLayout*> container) {
|
|||
|
||||
Auth().notifications().createManager();
|
||||
|
||||
if (advanced) {
|
||||
advanced->toggle(
|
||||
if (advancedSlide) {
|
||||
advancedSlide->toggle(
|
||||
!Global::NativeNotifications(),
|
||||
anim::type::normal);
|
||||
}
|
||||
}, native->lifetime());
|
||||
}
|
||||
if (advanced) {
|
||||
advanced->entity()->addClickHandler([=] {
|
||||
advanced->addClickHandler([=] {
|
||||
Ui::show(Box<NotificationsBox>());
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void SetupNotifications(not_null<Ui::VerticalLayout*> container) {
|
||||
AddDivider(container);
|
||||
AddSkip(container, st::settingsCheckboxesSkip);
|
||||
|
||||
auto wrap = object_ptr<Ui::VerticalLayout>(container);
|
||||
|
@ -226,7 +237,6 @@ Notifications::Notifications(QWidget *parent, not_null<UserData*> self)
|
|||
void Notifications::setupContent() {
|
||||
const auto content = Ui::CreateChild<Ui::VerticalLayout>(this);
|
||||
|
||||
AddSkip(content, st::settingsFirstDividerSkip);
|
||||
SetupNotifications(content);
|
||||
|
||||
Ui::ResizeFitChild(this, content);
|
||||
|
|
|
@ -57,7 +57,6 @@ QString PrivacyBase(ApiWrap::Privacy::Option option) {
|
|||
}
|
||||
|
||||
void SetupPrivacy(not_null<Ui::VerticalLayout*> container) {
|
||||
AddDivider(container);
|
||||
AddSkip(container);
|
||||
|
||||
AddSubsectionTitle(container, lng_settings_privacy_title);
|
||||
|
@ -482,7 +481,6 @@ PrivacySecurity::PrivacySecurity(QWidget *parent, not_null<UserData*> self)
|
|||
void PrivacySecurity::setupContent() {
|
||||
const auto content = Ui::CreateChild<Ui::VerticalLayout>(this);
|
||||
|
||||
AddSkip(content, st::settingsFirstDividerSkip);
|
||||
SetupPrivacy(content);
|
||||
SetupSecurity(content);
|
||||
SetupCalls(content);
|
||||
|
|
|
@ -78,7 +78,7 @@ void AbstractButton::mouseReleaseEvent(QMouseEvent *e) {
|
|||
emit clicked();
|
||||
}
|
||||
if (weak) {
|
||||
_clicks.fire({});
|
||||
_clicks.fire(e->button());
|
||||
}
|
||||
} else {
|
||||
setOver(false, StateChangeSource::ByHover);
|
||||
|
|
|
@ -43,7 +43,7 @@ public:
|
|||
_clickedCallback = std::move(callback);
|
||||
}
|
||||
|
||||
rpl::producer<> clicks() const {
|
||||
rpl::producer<Qt::MouseButton> clicks() const {
|
||||
return _clicks.events();
|
||||
}
|
||||
template <typename Handler>
|
||||
|
@ -100,7 +100,7 @@ private:
|
|||
|
||||
Fn<void()> _clickedCallback;
|
||||
|
||||
rpl::event_stream<> _clicks;
|
||||
rpl::event_stream<Qt::MouseButton> _clicks;
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -266,6 +266,11 @@ void RoundButton::setFullWidth(int newFullWidth) {
|
|||
refreshText();
|
||||
}
|
||||
|
||||
void RoundButton::setFullRadius(bool enabled) {
|
||||
_fullRadius = enabled;
|
||||
update();
|
||||
}
|
||||
|
||||
void RoundButton::refreshText() {
|
||||
_text = computeFullText();
|
||||
_textWidth = _text.isEmpty() ? 0 : _st.font->width(_text);
|
||||
|
@ -319,12 +324,24 @@ void RoundButton::paintEvent(QPaintEvent *e) {
|
|||
if (_fullWidthOverride < 0) {
|
||||
rounded = QRect(0, rounded.top(), innerWidth - _fullWidthOverride, rounded.height());
|
||||
}
|
||||
App::roundRect(p, myrtlrect(rounded), _st.textBg, ImageRoundRadius::Small);
|
||||
const auto drawRect = [&](const style::color &color) {
|
||||
const auto fill = myrtlrect(rounded);
|
||||
if (_fullRadius) {
|
||||
const auto radius = rounded.height() / 2;
|
||||
PainterHighQualityEnabler hq(p);
|
||||
p.setPen(Qt::NoPen);
|
||||
p.setBrush(color);
|
||||
p.drawRoundedRect(fill, radius, radius);
|
||||
} else {
|
||||
App::roundRect(p, fill, color, ImageRoundRadius::Small);
|
||||
}
|
||||
};
|
||||
drawRect(_st.textBg);
|
||||
|
||||
auto over = isOver();
|
||||
auto down = isDown();
|
||||
if (over || down) {
|
||||
App::roundRect(p, myrtlrect(rounded), _st.textBgOver, ImageRoundRadius::Small);
|
||||
drawRect(_st.textBgOver);
|
||||
}
|
||||
|
||||
auto ms = getms();
|
||||
|
@ -369,7 +386,9 @@ QImage RoundButton::prepareRippleMask() const {
|
|||
if (_fullWidthOverride < 0) {
|
||||
rounded = QRect(0, rounded.top(), innerWidth - _fullWidthOverride, rounded.height());
|
||||
}
|
||||
return RippleAnimation::roundRectMask(rounded.size(), st::buttonRadius);
|
||||
return RippleAnimation::roundRectMask(
|
||||
rounded.size(),
|
||||
_fullRadius ? (rounded.height() / 2) : st::buttonRadius);
|
||||
}
|
||||
|
||||
QPoint RoundButton::prepareRippleStartPosition() const {
|
||||
|
|
|
@ -120,6 +120,7 @@ public:
|
|||
int contentWidth() const;
|
||||
|
||||
void setFullWidth(int newFullWidth);
|
||||
void setFullRadius(bool enabled);
|
||||
|
||||
enum class TextTransform {
|
||||
NoTransform,
|
||||
|
@ -153,6 +154,7 @@ private:
|
|||
const style::RoundButton &_st;
|
||||
|
||||
TextTransform _transform = TextTransform::ToUpper;
|
||||
bool _fullRadius = false;
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -87,13 +87,15 @@ void SeparatePanel::updateTitlePosition() {
|
|||
|
||||
rpl::producer<> SeparatePanel::backRequests() const {
|
||||
return rpl::merge(
|
||||
_back->entity()->clicks(),
|
||||
_back->entity()->clicks(
|
||||
) | rpl::map([] { return rpl::empty_value(); }),
|
||||
_synteticBackRequests.events());
|
||||
}
|
||||
|
||||
rpl::producer<> SeparatePanel::closeRequests() const {
|
||||
return rpl::merge(
|
||||
_close->clicks(),
|
||||
_close->clicks(
|
||||
) | rpl::map([] { return rpl::empty_value(); }),
|
||||
_userCloseRequests.events());
|
||||
}
|
||||
|
||||
|
|
|
@ -293,11 +293,15 @@ void TermsBox::prepare() {
|
|||
return false;
|
||||
}
|
||||
return true;
|
||||
}) | rpl::map([] {
|
||||
return rpl::empty_value();
|
||||
}) | rpl::start_to_stream(_agreeClicks, lifetime());
|
||||
|
||||
if (_cancel) {
|
||||
addButton(_cancel, [=] {})->clicks(
|
||||
) | rpl::start_to_stream(_cancelClicks, lifetime());
|
||||
) | rpl::map([] {
|
||||
return rpl::empty_value();
|
||||
}) | rpl::start_to_stream(_cancelClicks, lifetime());
|
||||
}
|
||||
|
||||
if (age) {
|
||||
|
|
Loading…
Reference in New Issue