Check shortcuts / messages limits.

This commit is contained in:
John Preston 2024-03-01 12:29:03 +04:00
parent dd6768a476
commit ca4cbddba6
11 changed files with 253 additions and 51 deletions

View file

@ -2226,6 +2226,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_greeting_empty_title" = "New Greeting Message";
"lng_greeting_empty_about" = "Create greetings that will be automatically sent to new customers.";
"lng_greeting_message_placeholder" = "Add a Greeting";
"lng_greeting_limit_reached" = "You have too many quick replies. Remove one to add a greeting message.";
"lng_away_title" = "Away Message";
"lng_away_about" = "Automatically reply with a message when you are away.";
@ -2242,7 +2243,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_away_empty_title" = "New Away Message";
"lng_away_empty_about" = "Add messages that will be automatically sent when you are off.";
"lng_away_message_placeholder" = "Add an Away Message";
"lng_away_limit_reached" = "You have too many quick replies. Remove one to add an away message.";
"lng_business_edit_messages" = "Edit messages";
"lng_business_limit_reached#one" = "Limit of {count} message reached.";
"lng_business_limit_reached#other" = "Limit of {count} messages reached.";

View file

@ -114,10 +114,7 @@ std::optional<EmojiSection> SetIdEmojiSection(uint64 id) {
rpl::producer<std::vector<GifSection>> GifSectionsValue(
not_null<Main::Session*> session) {
const auto config = &session->account().appConfig();
return rpl::single(
rpl::empty_value()
) | rpl::then(
config->refreshed()
return config->value(
) | rpl::map([=] {
return config->get<std::vector<QString>>(
u"gif_search_emojies"_q,

View file

@ -2347,6 +2347,7 @@ void SetupRestrictionView(
});
state->label = makeLabel(value.text, st->premiumRequired.label);
}
state->updateGeometries();
}, widget->lifetime());
widget->sizeValue(

View file

@ -18,6 +18,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "settings/business/settings_shortcut_messages.h"
#include "ui/boxes/choose_date_time.h"
#include "ui/text/text_utilities.h"
#include "ui/toast/toast.h"
#include "ui/widgets/buttons.h"
#include "ui/widgets/checkbox.h"
#include "ui/wrap/slide_wrap.h"
@ -43,6 +44,8 @@ private:
void setupContent(not_null<Window::SessionController*> controller);
void save();
rpl::variable<bool> _canHave;
rpl::event_stream<> _deactivateOnAttempt;
rpl::variable<Data::BusinessRecipients> _recipients;
rpl::variable<Data::AwaySchedule> _schedule;
rpl::variable<bool> _enabled;
@ -231,13 +234,35 @@ void AwayMessage::setupContent(
.aboutMargins = st::peerAppearanceCoverLabelMargin,
});
const auto session = &controller->session();
_canHave = rpl::combine(
ShortcutsCountValue(session),
ShortcutsLimitValue(session),
ShortcutExistsValue(session, u"away"_q),
(_1 < _2) || _3);
Ui::AddSkip(content);
const auto enabled = content->add(object_ptr<Ui::SettingsButton>(
content,
tr::lng_away_enable(),
st::settingsButtonNoIcon
))->toggleOn(rpl::single(!disabled));
))->toggleOn(rpl::single(
!disabled
) | rpl::then(rpl::merge(
_canHave.value() | rpl::filter(!_1),
_deactivateOnAttempt.events() | rpl::map_to(false)
)));
_enabled = enabled->toggledValue();
_enabled.value() | rpl::filter(_1) | rpl::start_with_next([=] {
if (!_canHave.current()) {
controller->showToast({
.text = tr::lng_away_limit_reached(tr::now),
.adaptive = true,
});
_deactivateOnAttempt.fire({});
}
}, lifetime());
const auto wrap = content->add(
object_ptr<Ui::SlideWrap<Ui::VerticalLayout>>(
@ -254,11 +279,21 @@ void AwayMessage::setupContent(
object_ptr<Ui::VerticalLayout>(inner)));
const auto createInner = createWrap->entity();
Ui::AddSkip(createInner);
const auto create = createInner->add(object_ptr<Ui::SettingsButton>(
const auto create = AddButtonWithLabel(
createInner,
tr::lng_away_create(),
st::settingsButtonLightNoIcon
));
rpl::conditional(
ShortcutExistsValue(session, u"away"_q),
tr::lng_business_edit_messages(),
tr::lng_away_create()),
ShortcutMessagesCountValue(
session,
u"away"_q
) | rpl::map([=](int count) {
return count
? tr::lng_forum_messages(tr::now, lt_count, count)
: QString();
}),
st::settingsButtonLightNoIcon);
create->setClickedCallback([=] {
const auto owner = &controller->session().data();
const auto id = owner->shortcutMessages().emplaceShortcut("away");

View file

@ -18,6 +18,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "settings/business/settings_recipients_helper.h"
#include "ui/layers/generic_box.h"
#include "ui/text/text_utilities.h"
#include "ui/toast/toast.h"
#include "ui/widgets/box_content_divider.h"
#include "ui/widgets/buttons.h"
#include "ui/widgets/vertical_drum_picker.h"
@ -53,6 +54,8 @@ private:
Ui::RoundRect _bottomSkipRounding;
rpl::variable<Data::BusinessRecipients> _recipients;
rpl::variable<bool> _canHave;
rpl::event_stream<> _deactivateOnAttempt;
rpl::variable<int> _noActivityDays;
rpl::variable<bool> _enabled;
@ -198,14 +201,35 @@ void Greeting::setupContent(
.aboutMargins = st::peerAppearanceCoverLabelMargin,
});
const auto session = &controller->session();
_canHave = rpl::combine(
ShortcutsCountValue(session),
ShortcutsLimitValue(session),
ShortcutExistsValue(session, u"hello"_q),
(_1 < _2) || _3);
Ui::AddSkip(content);
const auto enabled = content->add(object_ptr<Ui::SettingsButton>(
content,
tr::lng_greeting_enable(),
st::settingsButtonNoIcon
))->toggleOn(rpl::single(!disabled));
))->toggleOn(rpl::single(
!disabled
) | rpl::then(rpl::merge(
_canHave.value() | rpl::filter(!_1),
_deactivateOnAttempt.events() | rpl::map_to(false)
)));
_enabled = enabled->toggledValue();
_enabled.value() | rpl::filter(_1) | rpl::start_with_next([=] {
if (!_canHave.current()) {
controller->showToast({
.text = tr::lng_greeting_limit_reached(tr::now),
.adaptive = true,
});
_deactivateOnAttempt.fire({});
}
}, lifetime());
Ui::AddSkip(content);
@ -237,11 +261,21 @@ void Greeting::setupContent(
object_ptr<Ui::VerticalLayout>(inner)));
const auto createInner = createWrap->entity();
Ui::AddSkip(createInner);
const auto create = createInner->add(object_ptr<Ui::SettingsButton>(
const auto create = AddButtonWithLabel(
createInner,
tr::lng_greeting_create(),
st::settingsButtonLightNoIcon
));
rpl::conditional(
ShortcutExistsValue(session, u"hello"_q),
tr::lng_business_edit_messages(),
tr::lng_greeting_create()),
ShortcutMessagesCountValue(
session,
u"hello"_q
) | rpl::map([=](int count) {
return count
? tr::lng_forum_messages(tr::now, lt_count, count)
: QString();
}),
st::settingsButtonLightNoIcon);
create->setClickedCallback([=] {
const auto owner = &controller->session().data();
const auto id = owner->shortcutMessages().emplaceShortcut("hello");

View file

@ -11,6 +11,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#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"
@ -42,6 +43,8 @@ private:
void setupContent(not_null<Window::SessionController*> controller);
void save();
rpl::variable<int> _count;
};
QuickReplies::QuickReplies(
@ -75,29 +78,47 @@ void QuickReplies::setupContent(
.about = tr::lng_replies_about(Ui::Text::WithEntities),
.aboutMargins = st::peerAppearanceCoverLabelMargin,
});
Ui::AddSkip(content);
const auto add = content->add(object_ptr<Ui::SettingsButton>(
content,
tr::lng_replies_add(),
st::settingsButtonNoIcon
));
const auto addWrap = content->add(
object_ptr<Ui::VerticalLayout>(content));
const auto owner = &controller->session().data();
const auto messages = &owner->shortcutMessages();
add->setClickedCallback([=] {
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)));
});
rpl::combine(
_count.value(),
ShortcutsLimitValue(&controller->session())
) | rpl::start_with_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
));
const auto dividerWrap = content->add(
object_ptr<Ui::VerticalLayout>(content));
add->setClickedCallback([=] {
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));
@ -108,7 +129,8 @@ void QuickReplies::setupContent(
const auto &shortcuts = messages->shortcuts();
auto i = 0;
for (const auto &[_, shortcut] : shortcuts.list) {
for (const auto &[_, shortcut]
: shortcuts.list | ranges::views::reverse) {
if (!shortcut.count) {
continue;
}
@ -132,18 +154,7 @@ void QuickReplies::setupContent(
while (old--) {
delete inner->widgetAt(0);
}
if (!inner->count()) {
while (dividerWrap->count()) {
delete dividerWrap->widgetAt(0);
}
} else if (!dividerWrap->count()) {
AddSkip(dividerWrap);
AddDivider(dividerWrap);
AddSkip(dividerWrap);
}
if (const auto width = content->width()) {
content->resizeToWidth(width);
}
_count = inner->count();
}, content->lifetime());
Ui::ResizeFitChild(this, content);

View file

@ -9,10 +9,14 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "boxes/filters/edit_filter_chats_list.h"
#include "boxes/filters/edit_filter_chats_preview.h"
#include "data/business/data_shortcut_messages.h"
#include "data/data_session.h"
#include "data/data_user.h"
#include "history/history.h"
#include "lang/lang_keys.h"
#include "main/main_account.h"
#include "main/main_app_config.h"
#include "main/main_session.h"
#include "settings/settings_common.h"
#include "ui/widgets/checkbox.h"
#include "ui/wrap/slide_wrap.h"
@ -291,4 +295,83 @@ void AddBusinessRecipientsSelector(
});
}
int ShortcutsCount(not_null<Main::Session*> session) {
const auto &shortcuts = session->data().shortcutMessages().shortcuts();
auto result = 0;
for (const auto &[_, shortcut] : shortcuts.list) {
if (shortcut.count > 0) {
++result;
}
}
return result;
}
rpl::producer<int> ShortcutsCountValue(not_null<Main::Session*> session) {
const auto messages = &session->data().shortcutMessages();
return rpl::single(rpl::empty) | rpl::then(
messages->shortcutsChanged()
) | rpl::map([=] {
return ShortcutsCount(session);
});
}
int ShortcutMessagesCount(
not_null<Main::Session*> session,
const QString &name) {
const auto &shortcuts = session->data().shortcutMessages().shortcuts();
for (const auto &[_, shortcut] : shortcuts.list) {
if (shortcut.name == name) {
return shortcut.count;
}
}
return 0;
}
rpl::producer<int> ShortcutMessagesCountValue(
not_null<Main::Session*> session,
const QString &name) {
const auto messages = &session->data().shortcutMessages();
return rpl::single(rpl::empty) | rpl::then(
messages->shortcutsChanged()
) | rpl::map([=] {
return ShortcutMessagesCount(session, name);
});
}
bool ShortcutExists(not_null<Main::Session*> session, const QString &name) {
return ShortcutMessagesCount(session, name) > 0;
}
rpl::producer<bool> ShortcutExistsValue(
not_null<Main::Session*> session,
const QString &name) {
return ShortcutMessagesCountValue(session, name)
| rpl::map(rpl::mappers::_1 > 0);
}
int ShortcutsLimit(not_null<Main::Session*> session) {
const auto appConfig = &session->account().appConfig();
return appConfig->get<int>("quick_replies_limit", 100);
}
rpl::producer<int> ShortcutsLimitValue(not_null<Main::Session*> session) {
const auto appConfig = &session->account().appConfig();
return appConfig->value() | rpl::map([=] {
return ShortcutsLimit(session);
});
}
int ShortcutMessagesLimit(not_null<Main::Session*> session) {
const auto appConfig = &session->account().appConfig();
return appConfig->get<int>("quick_reply_messages_limit", 20);
}
rpl::producer<int> ShortcutMessagesLimitValue(
not_null<Main::Session*> session) {
const auto appConfig = &session->account().appConfig();
return appConfig->value() | rpl::map([=] {
return ShortcutMessagesLimit(session);
});
}
} // namespace Settings

View file

@ -71,4 +71,26 @@ void AddBusinessRecipientsSelector(
not_null<Ui::VerticalLayout*> container,
BusinessRecipientsSelectorDescriptor &&descriptor);
[[nodiscard]] int ShortcutsCount(not_null<Main::Session*> session);
[[nodiscard]] rpl::producer<int> ShortcutsCountValue(
not_null<Main::Session*> session);
[[nodiscard]] int ShortcutMessagesCount(
not_null<Main::Session*> session,
const QString &name);
[[nodiscard]] rpl::producer<int> ShortcutMessagesCountValue(
not_null<Main::Session*> session,
const QString &name);
[[nodiscard]] bool ShortcutExists(
not_null<Main::Session*> session,
const QString &name);
[[nodiscard]] rpl::producer<bool> ShortcutExistsValue(
not_null<Main::Session*> session,
const QString &name);
[[nodiscard]] int ShortcutsLimit(not_null<Main::Session*> session);
[[nodiscard]] rpl::producer<int> ShortcutsLimitValue(
not_null<Main::Session*> session);
[[nodiscard]] int ShortcutMessagesLimit(not_null<Main::Session*> session);
[[nodiscard]] rpl::producer<int> ShortcutMessagesLimitValue(
not_null<Main::Session*> session);
} // namespace Settings

View file

@ -35,6 +35,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "inline_bots/inline_bot_result.h"
#include "lang/lang_keys.h"
#include "lang/lang_numbers_animation.h"
#include "main/main_account.h"
#include "main/main_app_config.h"
#include "main/main_session.h"
#include "menu/menu_send.h"
#include "settings/business/settings_quick_replies.h"
@ -259,6 +261,7 @@ private:
rpl::variable<BusinessShortcutId> _shortcutId;
rpl::variable<QString> _shortcut;
rpl::variable<Container> _container;
rpl::variable<int> _count;
std::shared_ptr<Ui::ChatStyle> _style;
std::shared_ptr<Ui::ChatTheme> _theme;
QPointer<ListWidget> _inner;
@ -618,9 +621,22 @@ void ShortcutMessages::setupComposeControls() {
};
_composeControls->setCurrentDialogsEntryState(state);
auto writeRestriction = rpl::combine(
_count.value(),
ShortcutMessagesLimitValue(_session)
) | rpl::map([=](int count, int limit) {
return (count >= limit)
? Controls::WriteRestriction{
.text = tr::lng_business_limit_reached(
tr::now,
lt_count,
limit),
.type = Controls::WriteRestrictionType::Rights,
} : Controls::WriteRestriction();
});
_composeControls->setHistory({
.history = _history.get(),
.writeRestriction = rpl::single(Controls::WriteRestriction()),
.writeRestriction = std::move(writeRestriction),
});
_composeControls->cancelRequests(
@ -831,7 +847,11 @@ rpl::producer<Data::MessagesSlice> ShortcutMessages::listSource(
) | rpl::map([=] {
return messages->list(shortcutId);
});
}) | rpl::flatten_latest();
}) | rpl::flatten_latest(
) | rpl::after_next([=](const Data::MessagesSlice &slice) {
_count = slice.fullCount.value_or(
messages->count(_shortcutId.current()));
});
}
bool ShortcutMessages::listAllowsMultiSelect() {

View file

@ -446,10 +446,6 @@ void SetupPremium(
button->addClickHandler([=] {
controller->showGiftPremiumsBox(u"gift"_q);
});
constexpr auto kNewExpiresAt = int(1735689600);
if (base::unixtime::now() < kNewExpiresAt) {
Ui::NewBadge::AddToRight(button);
}
}
Ui::AddSkip(container);
}

@ -1 +1 @@
Subproject commit 333587d95edefcae1ebaf8838d3f499639fc2de8
Subproject commit 14794d22210cb21b82db20aa55b1f3c8733b5fbd