init
Some checks failed
Docker. / Ubuntu (push) Has been cancelled
User-agent updater. / User-agent (push) Failing after 15s
Lock Threads / lock (push) Failing after 10s
Waiting for answer. / waiting-for-answer (push) Failing after 22s
Needs user action. / needs-user-action (push) Failing after 8s
Can't reproduce. / cant-reproduce (push) Failing after 8s
Close stale issues and PRs / stale (push) Has been cancelled
Some checks failed
Docker. / Ubuntu (push) Has been cancelled
User-agent updater. / User-agent (push) Failing after 15s
Lock Threads / lock (push) Failing after 10s
Waiting for answer. / waiting-for-answer (push) Failing after 22s
Needs user action. / needs-user-action (push) Failing after 8s
Can't reproduce. / cant-reproduce (push) Failing after 8s
Close stale issues and PRs / stale (push) Has been cancelled
This commit is contained in:
646
Telegram/SourceFiles/settings/business/settings_chat_intro.cpp
Normal file
646
Telegram/SourceFiles/settings/business/settings_chat_intro.cpp
Normal file
@@ -0,0 +1,646 @@
|
||||
/*
|
||||
This file is part of Telegram Desktop,
|
||||
the official desktop application for the Telegram messaging service.
|
||||
|
||||
For license and copyright information please follow this link:
|
||||
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
*/
|
||||
#include "settings/business/settings_chat_intro.h"
|
||||
|
||||
#include "api/api_premium.h"
|
||||
#include "boxes/peers/edit_peer_color_box.h" // ButtonStyleWithRightEmoji
|
||||
#include "chat_helpers/stickers_lottie.h"
|
||||
#include "chat_helpers/tabbed_panel.h"
|
||||
#include "chat_helpers/tabbed_selector.h"
|
||||
#include "core/application.h"
|
||||
#include "data/business/data_business_info.h"
|
||||
#include "data/data_document.h"
|
||||
#include "data/data_document_media.h"
|
||||
#include "data/data_session.h"
|
||||
#include "data/data_user.h"
|
||||
#include "history/view/media/history_view_media_common.h"
|
||||
#include "history/view/media/history_view_sticker_player.h"
|
||||
#include "history/view/history_view_about_view.h"
|
||||
#include "history/view/history_view_element.h"
|
||||
#include "history/history.h"
|
||||
#include "lang/lang_keys.h"
|
||||
#include "main/main_app_config.h"
|
||||
#include "main/main_session.h"
|
||||
#include "settings/business/settings_recipients_helper.h"
|
||||
#include "ui/chat/chat_style.h"
|
||||
#include "ui/chat/chat_theme.h"
|
||||
#include "ui/effects/path_shift_gradient.h"
|
||||
#include "ui/text/text_utilities.h"
|
||||
#include "ui/widgets/fields/input_field.h"
|
||||
#include "ui/widgets/buttons.h"
|
||||
#include "ui/wrap/vertical_layout.h"
|
||||
#include "ui/wrap/slide_wrap.h"
|
||||
#include "ui/painter.h"
|
||||
#include "ui/vertical_list.h"
|
||||
#include "window/themes/window_theme.h"
|
||||
#include "window/section_widget.h"
|
||||
#include "window/window_controller.h"
|
||||
#include "window/window_session_controller.h"
|
||||
#include "styles/style_chat.h"
|
||||
#include "styles/style_chat_helpers.h"
|
||||
#include "styles/style_layers.h"
|
||||
#include "styles/style_settings.h"
|
||||
|
||||
namespace Settings {
|
||||
namespace {
|
||||
|
||||
using namespace HistoryView;
|
||||
|
||||
class PreviewDelegate final : public DefaultElementDelegate {
|
||||
public:
|
||||
PreviewDelegate(
|
||||
not_null<QWidget*> parent,
|
||||
not_null<Ui::ChatStyle*> st,
|
||||
Fn<void()> update);
|
||||
|
||||
bool elementAnimationsPaused() override;
|
||||
not_null<Ui::PathShiftGradient*> elementPathShiftGradient() override;
|
||||
Context elementContext() override;
|
||||
|
||||
private:
|
||||
const not_null<QWidget*> _parent;
|
||||
const std::unique_ptr<Ui::PathShiftGradient> _pathGradient;
|
||||
|
||||
};
|
||||
|
||||
class PreviewWrap final : public Ui::RpWidget {
|
||||
public:
|
||||
PreviewWrap(
|
||||
not_null<QWidget*> parent,
|
||||
not_null<Main::Session*> session,
|
||||
rpl::producer<Data::ChatIntro> value);
|
||||
~PreviewWrap();
|
||||
|
||||
private:
|
||||
void paintEvent(QPaintEvent *e) override;
|
||||
|
||||
void resizeTo(int width);
|
||||
void prepare(rpl::producer<Data::ChatIntro> value);
|
||||
|
||||
const not_null<History*> _history;
|
||||
const std::unique_ptr<Ui::ChatTheme> _theme;
|
||||
const std::unique_ptr<Ui::ChatStyle> _style;
|
||||
const std::unique_ptr<PreviewDelegate> _delegate;
|
||||
|
||||
std::unique_ptr<AboutView> _view;
|
||||
QPoint _position;
|
||||
|
||||
};
|
||||
|
||||
class StickerPanel final {
|
||||
public:
|
||||
StickerPanel();
|
||||
~StickerPanel();
|
||||
|
||||
struct Descriptor {
|
||||
not_null<Window::SessionController*> controller;
|
||||
not_null<QWidget*> button;
|
||||
};
|
||||
void show(Descriptor &&descriptor);
|
||||
|
||||
struct CustomChosen {
|
||||
not_null<DocumentData*> sticker;
|
||||
};
|
||||
[[nodiscard]] rpl::producer<CustomChosen> someCustomChosen() const {
|
||||
return _someCustomChosen.events();
|
||||
}
|
||||
|
||||
private:
|
||||
void create(const Descriptor &descriptor);
|
||||
|
||||
base::unique_qptr<ChatHelpers::TabbedPanel> _panel;
|
||||
QPointer<QWidget> _panelButton;
|
||||
rpl::event_stream<CustomChosen> _someCustomChosen;
|
||||
|
||||
};
|
||||
|
||||
class ChatIntro final : public BusinessSection<ChatIntro> {
|
||||
public:
|
||||
ChatIntro(
|
||||
QWidget *parent,
|
||||
not_null<Window::SessionController*> controller);
|
||||
~ChatIntro();
|
||||
|
||||
[[nodiscard]] bool closeByOutsideClick() const override;
|
||||
[[nodiscard]] rpl::producer<QString> title() override;
|
||||
|
||||
void setInnerFocus() override {
|
||||
_setFocus();
|
||||
}
|
||||
|
||||
private:
|
||||
void setupContent(not_null<Window::SessionController*> controller);
|
||||
void save();
|
||||
|
||||
Fn<void()> _setFocus;
|
||||
|
||||
rpl::variable<Data::ChatIntro> _intro;
|
||||
|
||||
};
|
||||
|
||||
[[nodiscard]] int PartLimit(
|
||||
not_null<Main::Session*> session,
|
||||
const QString &key,
|
||||
int defaultValue) {
|
||||
return session->appConfig().get<int>(key, defaultValue);
|
||||
}
|
||||
|
||||
[[nodiscard]] not_null<Ui::InputField*> AddPartInput(
|
||||
not_null<Ui::VerticalLayout*> container,
|
||||
rpl::producer<QString> placeholder,
|
||||
QString current,
|
||||
int limit) {
|
||||
const auto field = container->add(
|
||||
object_ptr<Ui::InputField>(
|
||||
container,
|
||||
st::settingsChatIntroField,
|
||||
std::move(placeholder),
|
||||
current),
|
||||
st::settingsChatIntroFieldMargins);
|
||||
field->setMaxLength(limit);
|
||||
Ui::AddLengthLimitLabel(field, limit);
|
||||
return field;
|
||||
}
|
||||
|
||||
rpl::producer<std::shared_ptr<StickerPlayer>> IconPlayerValue(
|
||||
not_null<DocumentData*> sticker,
|
||||
Fn<void()> update) {
|
||||
const auto media = sticker->createMediaView();
|
||||
media->checkStickerLarge();
|
||||
media->goodThumbnailWanted();
|
||||
|
||||
return rpl::single() | rpl::then(
|
||||
sticker->session().downloaderTaskFinished()
|
||||
) | rpl::filter([=] {
|
||||
return media->loaded();
|
||||
}) | rpl::take(1) | rpl::map([=] {
|
||||
auto result = std::shared_ptr<StickerPlayer>();
|
||||
const auto info = sticker->sticker();
|
||||
const auto box = QSize(st::emojiSize, st::emojiSize);
|
||||
if (info->isLottie()) {
|
||||
result = std::make_shared<LottiePlayer>(
|
||||
ChatHelpers::LottiePlayerFromDocument(
|
||||
media.get(),
|
||||
ChatHelpers::StickerLottieSize::StickerEmojiSize,
|
||||
box,
|
||||
Lottie::Quality::High));
|
||||
} else if (info->isWebm()) {
|
||||
result = std::make_shared<WebmPlayer>(
|
||||
media->owner()->location(),
|
||||
media->bytes(),
|
||||
box);
|
||||
} else {
|
||||
result = std::make_shared<StaticStickerPlayer>(
|
||||
media->owner()->location(),
|
||||
media->bytes(),
|
||||
box);
|
||||
}
|
||||
result->setRepaintCallback(update);
|
||||
return result;
|
||||
});
|
||||
}
|
||||
|
||||
[[nodiscard]] object_ptr<Ui::SettingsButton> CreateIntroStickerButton(
|
||||
not_null<Ui::RpWidget*> parent,
|
||||
std::shared_ptr<ChatHelpers::Show> show,
|
||||
rpl::producer<DocumentData*> stickerValue,
|
||||
Fn<void(DocumentData*)> stickerChosen) {
|
||||
const auto button = ButtonStyleWithRightEmoji(
|
||||
parent,
|
||||
tr::lng_chat_intro_random_sticker(tr::now),
|
||||
st::settingsButtonNoIcon);
|
||||
auto result = Settings::CreateButtonWithIcon(
|
||||
parent,
|
||||
tr::lng_chat_intro_choose_sticker(),
|
||||
*button.st);
|
||||
const auto raw = result.data();
|
||||
|
||||
const auto right = Ui::CreateChild<Ui::RpWidget>(raw);
|
||||
right->show();
|
||||
|
||||
struct State {
|
||||
StickerPanel panel;
|
||||
DocumentData *sticker = nullptr;
|
||||
std::shared_ptr<StickerPlayer> player;
|
||||
rpl::lifetime playerLifetime;
|
||||
};
|
||||
const auto state = right->lifetime().make_state<State>();
|
||||
state->panel.someCustomChosen(
|
||||
) | rpl::on_next([=](StickerPanel::CustomChosen chosen) {
|
||||
stickerChosen(chosen.sticker);
|
||||
}, raw->lifetime());
|
||||
|
||||
std::move(
|
||||
stickerValue
|
||||
) | rpl::on_next([=](DocumentData *sticker) {
|
||||
state->sticker = sticker;
|
||||
if (sticker) {
|
||||
right->resize(button.emojiWidth + button.added, right->height());
|
||||
IconPlayerValue(
|
||||
sticker,
|
||||
[=] { right->update(); }
|
||||
) | rpl::on_next([=](
|
||||
std::shared_ptr<StickerPlayer> player) {
|
||||
state->player = std::move(player);
|
||||
right->update();
|
||||
}, state->playerLifetime);
|
||||
} else {
|
||||
state->playerLifetime.destroy();
|
||||
state->player = nullptr;
|
||||
right->resize(button.noneWidth + button.added, right->height());
|
||||
right->update();
|
||||
}
|
||||
}, right->lifetime());
|
||||
|
||||
rpl::combine(
|
||||
raw->sizeValue(),
|
||||
right->widthValue()
|
||||
) | rpl::on_next([=](QSize outer, int width) {
|
||||
right->resize(width, outer.height());
|
||||
const auto skip = st::settingsButton.padding.right();
|
||||
right->moveToRight(skip - button.added, 0, outer.width());
|
||||
}, right->lifetime());
|
||||
|
||||
right->paintRequest(
|
||||
) | rpl::on_next([=] {
|
||||
auto p = QPainter(right);
|
||||
const auto height = right->height();
|
||||
if (state->player) {
|
||||
if (state->player->ready()) {
|
||||
const auto frame = state->player->frame(
|
||||
QSize(st::emojiSize, st::emojiSize),
|
||||
QColor(0, 0, 0, 0),
|
||||
false,
|
||||
crl::now(),
|
||||
!right->window()->isActiveWindow()).image;
|
||||
const auto target = DownscaledSize(
|
||||
frame.size(),
|
||||
QSize(st::emojiSize, st::emojiSize));
|
||||
p.drawImage(
|
||||
QRect(
|
||||
button.added + (st::emojiSize - target.width()) / 2,
|
||||
(height - target.height()) / 2,
|
||||
target.width(),
|
||||
target.height()),
|
||||
frame);
|
||||
state->player->markFrameShown();
|
||||
}
|
||||
} else {
|
||||
const auto &font = st::normalFont;
|
||||
p.setFont(font);
|
||||
p.setPen(st::windowActiveTextFg);
|
||||
p.drawText(
|
||||
QPoint(
|
||||
button.added,
|
||||
(height - font->height) / 2 + font->ascent),
|
||||
tr::lng_chat_intro_random_sticker(tr::now));
|
||||
}
|
||||
}, right->lifetime());
|
||||
|
||||
raw->setClickedCallback([=] {
|
||||
if (const auto controller = show->resolveWindow()) {
|
||||
state->panel.show({
|
||||
.controller = controller,
|
||||
.button = right,
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
PreviewDelegate::PreviewDelegate(
|
||||
not_null<QWidget*> parent,
|
||||
not_null<Ui::ChatStyle*> st,
|
||||
Fn<void()> update)
|
||||
: _parent(parent)
|
||||
, _pathGradient(MakePathShiftGradient(st, update)) {
|
||||
}
|
||||
|
||||
bool PreviewDelegate::elementAnimationsPaused() {
|
||||
return _parent->window()->isActiveWindow();
|
||||
}
|
||||
|
||||
auto PreviewDelegate::elementPathShiftGradient()
|
||||
-> not_null<Ui::PathShiftGradient*> {
|
||||
return _pathGradient.get();
|
||||
}
|
||||
|
||||
Context PreviewDelegate::elementContext() {
|
||||
return Context::History;
|
||||
}
|
||||
|
||||
PreviewWrap::PreviewWrap(
|
||||
not_null<QWidget*> parent,
|
||||
not_null<Main::Session*> session,
|
||||
rpl::producer<Data::ChatIntro> value)
|
||||
: RpWidget(parent)
|
||||
, _history(session->data().history(session->userPeerId()))
|
||||
, _theme(Window::Theme::DefaultChatThemeOn(lifetime()))
|
||||
, _style(std::make_unique<Ui::ChatStyle>(
|
||||
_history->session().colorIndicesValue()))
|
||||
, _delegate(std::make_unique<PreviewDelegate>(
|
||||
parent,
|
||||
_style.get(),
|
||||
[=] { update(); }))
|
||||
, _position(0, st::msgMargin.bottom()) {
|
||||
_style->apply(_theme.get());
|
||||
|
||||
session->data().viewRepaintRequest(
|
||||
) | rpl::on_next([=](not_null<const Element*> view) {
|
||||
if (view == _view->view()) {
|
||||
update();
|
||||
}
|
||||
}, lifetime());
|
||||
|
||||
session->downloaderTaskFinished() | rpl::on_next([=] {
|
||||
update();
|
||||
}, lifetime());
|
||||
|
||||
prepare(std::move(value));
|
||||
}
|
||||
|
||||
PreviewWrap::~PreviewWrap() {
|
||||
_view = nullptr;
|
||||
}
|
||||
|
||||
void PreviewWrap::prepare(rpl::producer<Data::ChatIntro> value) {
|
||||
_view = std::make_unique<AboutView>(
|
||||
_history.get(),
|
||||
_delegate.get());
|
||||
|
||||
std::move(value) | rpl::on_next([=](Data::ChatIntro intro) {
|
||||
_view->make(std::move(intro), true);
|
||||
if (width() >= st::msgMinWidth) {
|
||||
resizeTo(width());
|
||||
}
|
||||
update();
|
||||
}, lifetime());
|
||||
|
||||
widthValue(
|
||||
) | rpl::filter([=](int width) {
|
||||
return width >= st::msgMinWidth;
|
||||
}) | rpl::on_next([=](int width) {
|
||||
resizeTo(width);
|
||||
}, lifetime());
|
||||
}
|
||||
|
||||
void PreviewWrap::resizeTo(int width) {
|
||||
const auto height = _position.y()
|
||||
+ _view->view()->resizeGetHeight(width)
|
||||
+ _position.y()
|
||||
+ st::msgServiceMargin.top()
|
||||
+ st::msgServiceGiftBoxTopSkip
|
||||
- st::msgServiceMargin.bottom();
|
||||
resize(width, height);
|
||||
}
|
||||
|
||||
void PreviewWrap::paintEvent(QPaintEvent *e) {
|
||||
auto p = Painter(this);
|
||||
|
||||
const auto clip = e->rect();
|
||||
if (!clip.isEmpty()) {
|
||||
p.setClipRect(clip);
|
||||
Window::SectionWidget::PaintBackground(
|
||||
p,
|
||||
_theme.get(),
|
||||
QSize(width(), window()->height()),
|
||||
clip);
|
||||
}
|
||||
|
||||
auto context = _theme->preparePaintContext(
|
||||
_style.get(),
|
||||
rect(),
|
||||
e->rect(),
|
||||
!window()->isActiveWindow());
|
||||
p.translate(_position);
|
||||
_view->view()->draw(p, context);
|
||||
}
|
||||
|
||||
StickerPanel::StickerPanel() = default;
|
||||
|
||||
StickerPanel::~StickerPanel() = default;
|
||||
|
||||
void StickerPanel::show(Descriptor &&descriptor) {
|
||||
if (!_panel) {
|
||||
create(descriptor);
|
||||
|
||||
_panel->shownValue(
|
||||
) | rpl::filter([=] {
|
||||
return (_panelButton != nullptr);
|
||||
}) | rpl::on_next([=](bool shown) {
|
||||
if (shown) {
|
||||
_panelButton->installEventFilter(_panel.get());
|
||||
} else {
|
||||
_panelButton->removeEventFilter(_panel.get());
|
||||
}
|
||||
}, _panel->lifetime());
|
||||
}
|
||||
const auto button = descriptor.button;
|
||||
if (const auto previous = _panelButton.data()) {
|
||||
if (previous != button) {
|
||||
previous->removeEventFilter(_panel.get());
|
||||
}
|
||||
}
|
||||
_panelButton = button;
|
||||
const auto parent = _panel->parentWidget();
|
||||
const auto global = button->mapToGlobal(QPoint());
|
||||
const auto local = parent->mapFromGlobal(global);
|
||||
_panel->moveBottomRight(
|
||||
local.y() + (st::normalFont->height / 2),
|
||||
local.x() + button->width() * 3);
|
||||
_panel->toggleAnimated();
|
||||
}
|
||||
|
||||
void StickerPanel::create(const Descriptor &descriptor) {
|
||||
using Selector = ChatHelpers::TabbedSelector;
|
||||
using Descriptor = ChatHelpers::TabbedSelectorDescriptor;
|
||||
using Mode = ChatHelpers::TabbedSelector::Mode;
|
||||
const auto controller = descriptor.controller;
|
||||
const auto body = controller->window().widget()->bodyWidget();
|
||||
_panel = base::make_unique_q<ChatHelpers::TabbedPanel>(
|
||||
body,
|
||||
controller,
|
||||
object_ptr<Selector>(
|
||||
nullptr,
|
||||
Descriptor{
|
||||
.show = controller->uiShow(),
|
||||
.st = st::backgroundEmojiPan,
|
||||
.level = Window::GifPauseReason::Layer,
|
||||
.mode = Mode::ChatIntro,
|
||||
.features = {
|
||||
.megagroupSet = false,
|
||||
.stickersSettings = false,
|
||||
.openStickerSets = false,
|
||||
},
|
||||
}));
|
||||
_panel->setDropDown(false);
|
||||
_panel->setDesiredHeightValues(
|
||||
1.,
|
||||
st::emojiPanMinHeight / 2,
|
||||
st::emojiPanMinHeight);
|
||||
_panel->hide();
|
||||
|
||||
_panel->selector()->fileChosen(
|
||||
) | rpl::on_next([=](ChatHelpers::FileChosen data) {
|
||||
_someCustomChosen.fire({ data.document });
|
||||
_panel->hideAnimated();
|
||||
}, _panel->lifetime());
|
||||
}
|
||||
|
||||
ChatIntro::ChatIntro(
|
||||
QWidget *parent,
|
||||
not_null<Window::SessionController*> controller)
|
||||
: BusinessSection(parent, controller) {
|
||||
setupContent(controller);
|
||||
}
|
||||
|
||||
ChatIntro::~ChatIntro() {
|
||||
if (!Core::Quitting()) {
|
||||
save();
|
||||
}
|
||||
}
|
||||
|
||||
bool ChatIntro::closeByOutsideClick() const {
|
||||
return false;
|
||||
}
|
||||
|
||||
rpl::producer<QString> ChatIntro::title() {
|
||||
return tr::lng_chat_intro_title();
|
||||
}
|
||||
|
||||
[[nodiscard]] rpl::producer<Data::ChatIntro> IntroWithRandomSticker(
|
||||
not_null<Main::Session*> session,
|
||||
rpl::producer<Data::ChatIntro> intro) {
|
||||
auto random = rpl::single(
|
||||
Api::RandomHelloStickerValue(session)
|
||||
) | rpl::then(rpl::duplicate(
|
||||
intro
|
||||
) | rpl::map([=](const Data::ChatIntro &intro) {
|
||||
return intro.sticker;
|
||||
}) | rpl::distinct_until_changed(
|
||||
) | rpl::filter([](DocumentData *sticker) {
|
||||
return !sticker;
|
||||
}) | rpl::map([=] {
|
||||
return Api::RandomHelloStickerValue(session);
|
||||
})) | rpl::flatten_latest();
|
||||
|
||||
return rpl::combine(
|
||||
std::move(intro),
|
||||
std::move(random)
|
||||
) | rpl::map([=](Data::ChatIntro intro, DocumentData *hello) {
|
||||
if (!intro.sticker) {
|
||||
intro.sticker = hello;
|
||||
}
|
||||
return intro;
|
||||
});
|
||||
}
|
||||
|
||||
void ChatIntro::setupContent(
|
||||
not_null<Window::SessionController*> controller) {
|
||||
using namespace rpl::mappers;
|
||||
|
||||
const auto content = Ui::CreateChild<Ui::VerticalLayout>(this);
|
||||
const auto session = &controller->session();
|
||||
_intro = controller->session().user()->businessDetails().intro;
|
||||
|
||||
const auto change = [=](Fn<void(Data::ChatIntro &)> modify) {
|
||||
auto intro = _intro.current();
|
||||
modify(intro);
|
||||
_intro = intro;
|
||||
};
|
||||
|
||||
content->add(
|
||||
object_ptr<PreviewWrap>(
|
||||
content,
|
||||
session,
|
||||
IntroWithRandomSticker(session, _intro.value())),
|
||||
style::margins());
|
||||
|
||||
const auto title = AddPartInput(
|
||||
content,
|
||||
tr::lng_chat_intro_enter_title(),
|
||||
_intro.current().title,
|
||||
PartLimit(session, u"intro_title_length_limit"_q, 32));
|
||||
const auto description = AddPartInput(
|
||||
content,
|
||||
tr::lng_chat_intro_enter_message(),
|
||||
_intro.current().description,
|
||||
PartLimit(session, u"intro_description_length_limit"_q, 70));
|
||||
content->add(CreateIntroStickerButton(
|
||||
content,
|
||||
controller->uiShow(),
|
||||
_intro.value() | rpl::map([](const Data::ChatIntro &intro) {
|
||||
return intro.sticker;
|
||||
}) | rpl::distinct_until_changed(),
|
||||
[=](DocumentData *sticker) {
|
||||
change([&](Data::ChatIntro &intro) {
|
||||
intro.sticker = sticker;
|
||||
});
|
||||
}));
|
||||
Ui::AddSkip(content);
|
||||
|
||||
title->changes() | rpl::on_next([=] {
|
||||
change([&](Data::ChatIntro &intro) {
|
||||
intro.title = title->getLastText();
|
||||
});
|
||||
}, title->lifetime());
|
||||
|
||||
description->changes() | rpl::on_next([=] {
|
||||
change([&](Data::ChatIntro &intro) {
|
||||
intro.description = description->getLastText();
|
||||
});
|
||||
}, description->lifetime());
|
||||
|
||||
_setFocus = [=] {
|
||||
title->setFocusFast();
|
||||
};
|
||||
|
||||
Ui::AddDividerText(
|
||||
content,
|
||||
tr::lng_chat_intro_about(),
|
||||
st::peerAppearanceDividerTextMargin);
|
||||
Ui::AddSkip(content);
|
||||
|
||||
const auto resetWrap = content->add(
|
||||
object_ptr<Ui::SlideWrap<Ui::SettingsButton>>(
|
||||
content,
|
||||
object_ptr<Ui::SettingsButton>(
|
||||
content,
|
||||
tr::lng_chat_intro_reset(),
|
||||
st::settingsAttentionButton
|
||||
)));
|
||||
resetWrap->toggleOn(
|
||||
_intro.value() | rpl::map([](const Data::ChatIntro &intro) {
|
||||
return !!intro;
|
||||
}));
|
||||
resetWrap->entity()->setClickedCallback([=] {
|
||||
_intro = Data::ChatIntro();
|
||||
title->clear();
|
||||
description->clear();
|
||||
title->setFocus();
|
||||
});
|
||||
|
||||
Ui::ResizeFitChild(this, content);
|
||||
}
|
||||
|
||||
void ChatIntro::save() {
|
||||
const auto fail = [=](QString error) {
|
||||
};
|
||||
controller()->session().data().businessInfo().saveChatIntro(
|
||||
_intro.current(),
|
||||
fail);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
Type ChatIntroId() {
|
||||
return ChatIntro::Id();
|
||||
}
|
||||
|
||||
} // namespace Settings
|
||||
Reference in New Issue
Block a user