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
Close stale issues and PRs / stale (push) Successful in 13s
Needs user action. / needs-user-action (push) Failing after 8s
Can't reproduce. / cant-reproduce (push) Failing after 8s
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
Close stale issues and PRs / stale (push) Successful in 13s
Needs user action. / needs-user-action (push) Failing after 8s
Can't reproduce. / cant-reproduce (push) Failing after 8s
This commit is contained in:
@@ -0,0 +1,238 @@
|
||||
/*
|
||||
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_quick_replies.h"
|
||||
|
||||
#include "boxes/premium_preview_box.h"
|
||||
#include "core/application.h"
|
||||
#include "data/business/data_shortcut_messages.h"
|
||||
#include "data/data_session.h"
|
||||
#include "lang/lang_keys.h"
|
||||
#include "main/main_account.h"
|
||||
#include "main/main_session.h"
|
||||
#include "settings/business/settings_recipients_helper.h"
|
||||
#include "settings/business/settings_shortcut_messages.h"
|
||||
#include "ui/layers/generic_box.h"
|
||||
#include "ui/text/text_utilities.h"
|
||||
#include "ui/widgets/buttons.h"
|
||||
#include "ui/widgets/fields/input_field.h"
|
||||
#include "ui/wrap/slide_wrap.h"
|
||||
#include "ui/wrap/vertical_layout.h"
|
||||
#include "ui/vertical_list.h"
|
||||
#include "window/window_session_controller.h"
|
||||
#include "styles/style_chat_helpers.h"
|
||||
#include "styles/style_layers.h"
|
||||
#include "styles/style_settings.h"
|
||||
|
||||
namespace Settings {
|
||||
namespace {
|
||||
|
||||
constexpr auto kShortcutLimit = 32;
|
||||
|
||||
class QuickReplies : public BusinessSection<QuickReplies> {
|
||||
public:
|
||||
QuickReplies(
|
||||
QWidget *parent,
|
||||
not_null<Window::SessionController*> controller);
|
||||
~QuickReplies();
|
||||
|
||||
[[nodiscard]] rpl::producer<QString> title() override;
|
||||
|
||||
private:
|
||||
void setupContent(not_null<Window::SessionController*> controller);
|
||||
|
||||
rpl::variable<int> _count;
|
||||
|
||||
};
|
||||
|
||||
QuickReplies::QuickReplies(
|
||||
QWidget *parent,
|
||||
not_null<Window::SessionController*> controller)
|
||||
: BusinessSection(parent, controller) {
|
||||
setupContent(controller);
|
||||
}
|
||||
|
||||
QuickReplies::~QuickReplies() = default;
|
||||
|
||||
rpl::producer<QString> QuickReplies::title() {
|
||||
return tr::lng_replies_title();
|
||||
}
|
||||
|
||||
void QuickReplies::setupContent(
|
||||
not_null<Window::SessionController*> controller) {
|
||||
using namespace rpl::mappers;
|
||||
|
||||
const auto content = Ui::CreateChild<Ui::VerticalLayout>(this);
|
||||
|
||||
AddDividerTextWithLottie(content, {
|
||||
.lottie = u"writing"_q,
|
||||
.lottieSize = st::settingsCloudPasswordIconSize,
|
||||
.lottieMargins = st::peerAppearanceIconPadding,
|
||||
.showFinished = showFinishes(),
|
||||
.about = tr::lng_replies_about(tr::marked),
|
||||
.aboutMargins = st::peerAppearanceCoverLabelMargin,
|
||||
});
|
||||
Ui::AddSkip(content);
|
||||
|
||||
const auto addWrap = content->add(
|
||||
object_ptr<Ui::VerticalLayout>(content));
|
||||
|
||||
const auto owner = &controller->session().data();
|
||||
const auto messages = &owner->shortcutMessages();
|
||||
|
||||
rpl::combine(
|
||||
_count.value(),
|
||||
ShortcutsLimitValue(&controller->session())
|
||||
) | rpl::on_next([=](int count, int limit) {
|
||||
while (addWrap->count()) {
|
||||
delete addWrap->widgetAt(0);
|
||||
}
|
||||
if (count < limit) {
|
||||
const auto add = addWrap->add(object_ptr<Ui::SettingsButton>(
|
||||
addWrap,
|
||||
tr::lng_replies_add(),
|
||||
st::settingsButtonNoIcon
|
||||
));
|
||||
|
||||
add->setClickedCallback([=] {
|
||||
if (!controller->session().premium()) {
|
||||
ShowPremiumPreviewToBuy(
|
||||
controller,
|
||||
PremiumFeature::QuickReplies);
|
||||
return;
|
||||
}
|
||||
const auto submit = [=](QString name, Fn<void()> close) {
|
||||
const auto id = messages->emplaceShortcut(name);
|
||||
showOther(ShortcutMessagesId(id));
|
||||
close();
|
||||
};
|
||||
controller->show(Box(
|
||||
EditShortcutNameBox,
|
||||
QString(),
|
||||
crl::guard(this, submit)));
|
||||
});
|
||||
if (count > 0) {
|
||||
AddSkip(addWrap);
|
||||
AddDivider(addWrap);
|
||||
AddSkip(addWrap);
|
||||
}
|
||||
}
|
||||
if (const auto width = content->width()) {
|
||||
content->resizeToWidth(width);
|
||||
}
|
||||
}, lifetime());
|
||||
|
||||
const auto inner = content->add(
|
||||
object_ptr<Ui::VerticalLayout>(content));
|
||||
rpl::single(rpl::empty) | rpl::then(
|
||||
messages->shortcutsChanged()
|
||||
) | rpl::on_next([=] {
|
||||
auto old = inner->count();
|
||||
|
||||
const auto &shortcuts = messages->shortcuts();
|
||||
for (const auto &[_, shortcut]
|
||||
: shortcuts.list | ranges::views::reverse) {
|
||||
if (!shortcut.count) {
|
||||
continue;
|
||||
}
|
||||
const auto name = shortcut.name;
|
||||
AddButtonWithLabel(
|
||||
inner,
|
||||
rpl::single('/' + name),
|
||||
tr::lng_forum_messages(
|
||||
lt_count,
|
||||
rpl::single(1. * shortcut.count)),
|
||||
st::settingsButtonNoIcon
|
||||
)->setClickedCallback([=] {
|
||||
const auto id = messages->emplaceShortcut(name);
|
||||
showOther(ShortcutMessagesId(id));
|
||||
});
|
||||
if (old) {
|
||||
delete inner->widgetAt(0);
|
||||
--old;
|
||||
}
|
||||
}
|
||||
while (old--) {
|
||||
delete inner->widgetAt(0);
|
||||
}
|
||||
_count = inner->count();
|
||||
}, content->lifetime());
|
||||
|
||||
Ui::ResizeFitChild(this, content);
|
||||
}
|
||||
|
||||
[[nodiscard]] bool ValidShortcutName(const QString &name) {
|
||||
if (name.isEmpty() || name.size() > kShortcutLimit) {
|
||||
return false;
|
||||
}
|
||||
for (const auto &ch : name) {
|
||||
if (!ch.isLetterOrNumber()
|
||||
&& (ch != QChar('_'))
|
||||
&& (ch.unicode() != 0x200c)
|
||||
&& (ch.unicode() != 0x00b7)
|
||||
&& (ch.unicode() < 0x0d80 || ch.unicode() > 0x0dff)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
Type QuickRepliesId() {
|
||||
return QuickReplies::Id();
|
||||
}
|
||||
|
||||
void EditShortcutNameBox(
|
||||
not_null<Ui::GenericBox*> box,
|
||||
QString name,
|
||||
Fn<void(QString, Fn<void()>)> submit) {
|
||||
name = name.trimmed();
|
||||
const auto editing = !name.isEmpty();
|
||||
box->setTitle(editing
|
||||
? tr::lng_replies_edit_title()
|
||||
: tr::lng_replies_add_title());
|
||||
box->addRow(object_ptr<Ui::FlatLabel>(
|
||||
box,
|
||||
(editing
|
||||
? tr::lng_replies_edit_about()
|
||||
: tr::lng_replies_add_shortcut()),
|
||||
st::settingsAddReplyLabel));
|
||||
const auto field = box->addRow(object_ptr<Ui::InputField>(
|
||||
box,
|
||||
st::settingsAddReplyField,
|
||||
tr::lng_replies_add_placeholder(),
|
||||
name));
|
||||
box->setFocusCallback([=] {
|
||||
field->setFocusFast();
|
||||
});
|
||||
field->selectAll();
|
||||
field->setMaxLength(kShortcutLimit * 2);
|
||||
|
||||
Ui::AddLengthLimitLabel(field, kShortcutLimit);
|
||||
|
||||
const auto callback = [=] {
|
||||
const auto name = field->getLastText().trimmed();
|
||||
if (!ValidShortcutName(name)) {
|
||||
field->showError();
|
||||
} else {
|
||||
submit(name, [weak = base::make_weak(box)] {
|
||||
if (const auto strong = weak.get()) {
|
||||
strong->closeBox();
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
field->submits(
|
||||
) | rpl::on_next(callback, field->lifetime());
|
||||
box->addButton(tr::lng_settings_save(), callback);
|
||||
box->addButton(tr::lng_cancel(), [=] {
|
||||
box->closeBox();
|
||||
});
|
||||
}
|
||||
|
||||
} // namespace Settings
|
||||
Reference in New Issue
Block a user