Show length limit in chat intro fields.

This commit is contained in:
John Preston 2024-03-20 13:17:05 +04:00
parent 98ce91df39
commit 0887348611
5 changed files with 113 additions and 89 deletions

View file

@ -1019,14 +1019,8 @@ void EditTagBox(
struct State {
std::unique_ptr<Ui::Text::CustomEmoji> custom;
QImage image;
rpl::variable<int> length;
};
const auto state = field->lifetime().make_state<State>();
state->length = rpl::single(
int(title.size())
) | rpl::then(field->changes() | rpl::map([=] {
return int(field->getLastText().size());
}));
if (const auto customId = id.custom()) {
state->custom = owner->customEmojiManager().create(
@ -1059,28 +1053,8 @@ void EditTagBox(
}
}
}, field->lifetime());
const auto warning = Ui::CreateChild<Ui::FlatLabel>(
field,
state->length.value() | rpl::map([](int count) {
return (count > kTagNameLimit / 2)
? QString::number(kTagNameLimit - count)
: QString();
}),
st::editTagLimit);
state->length.value() | rpl::map(
rpl::mappers::_1 > kTagNameLimit
) | rpl::start_with_next([=](bool exceeded) {
warning->setTextColorOverride(exceeded
? st::attentionButtonFg->c
: std::optional<QColor>());
}, warning->lifetime());
rpl::combine(
field->sizeValue(),
warning->sizeValue()
) | rpl::start_with_next([=] {
warning->moveToRight(0, st::editTagField.textMargins.top());
}, warning->lifetime());
warning->setAttribute(Qt::WA_TransparentForMouseEvents);
AddLengthLimitLabel(field, kTagNameLimit);
const auto save = [=] {
const auto text = field->getLastText();
@ -1840,4 +1814,40 @@ bool ItemHasTtl(HistoryItem *item) {
: false;
}
void AddLengthLimitLabel(not_null<Ui::InputField*> field, int limit) {
struct State {
rpl::variable<int> length;
};
const auto state = field->lifetime().make_state<State>();
state->length = rpl::single(
rpl::empty
) | rpl::then(field->changes()) | rpl::map([=] {
return int(field->getLastText().size());
});
auto warningText = state->length.value() | rpl::map([=](int count) {
const auto threshold = std::min(limit / 2, 9);
const auto left = limit - count;
return (left < threshold) ? QString::number(left) : QString();
});
const auto warning = Ui::CreateChild<Ui::FlatLabel>(
field.get(),
std::move(warningText),
st::editTagLimit);
state->length.value() | rpl::map(
rpl::mappers::_1 > limit
) | rpl::start_with_next([=](bool exceeded) {
warning->setTextColorOverride(exceeded
? st::attentionButtonFg->c
: std::optional<QColor>());
}, warning->lifetime());
rpl::combine(
field->sizeValue(),
warning->sizeValue()
) | rpl::start_with_next([=] {
warning->moveToRight(0, 0);
}, warning->lifetime());
warning->setAttribute(Qt::WA_TransparentForMouseEvents);
}
} // namespace HistoryView

View file

@ -123,4 +123,6 @@ void AddEmojiPacksAction(
[[nodiscard]] bool ItemHasTtl(HistoryItem *item);
void AddLengthLimitLabel(not_null<Ui::InputField*> field, int limit);
} // namespace HistoryView

View file

@ -16,9 +16,12 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "data/data_document.h"
#include "data/data_session.h"
#include "history/view/history_view_about_view.h"
#include "history/view/history_view_context_menu.h"
#include "history/view/history_view_element.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/business/settings_recipients_helper.h"
#include "ui/chat/chat_style.h"
@ -141,6 +144,30 @@ private:
};
[[nodiscard]] int PartLimit(
not_null<Main::Session*> session,
const QString &key,
int defaultValue) {
return session->account().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,
tr::lng_chat_intro_enter_title(),
current),
st::settingsChatIntroFieldMargins);
field->setMaxLength(limit);
HistoryView::AddLengthLimitLabel(field, limit);
return field;
}
[[nodiscard]] object_ptr<Ui::SettingsButton> CreateIntroStickerButton(
not_null<Ui::RpWidget*> parent,
std::shared_ptr<ChatHelpers::Show> show,
@ -266,6 +293,10 @@ PreviewWrap::PreviewWrap(
}
}, lifetime());
session->downloaderTaskFinished() | rpl::start_with_next([=] {
update();
}, lifetime());
prepare(std::move(value));
}
@ -438,19 +469,28 @@ rpl::producer<QString> ChatIntro::title() {
[[nodiscard]] rpl::producer<Data::ChatIntro> IntroWithRandomSticker(
not_null<Main::Session*> session,
rpl::producer<Data::ChatIntro> intro) {
return std::move(intro) | rpl::map([=](Data::ChatIntro intro)
-> rpl::producer<Data::ChatIntro> {
if (intro.sticker) {
return rpl::single(std::move(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 Api::RandomHelloStickerValue(
session
) | rpl::map([=](DocumentData *sticker) {
auto copy = intro;
copy.sticker = sticker;
return copy;
});
}) | rpl::flatten_latest();
return intro;
});
}
void ChatIntro::setupContent(
@ -458,7 +498,8 @@ void ChatIntro::setupContent(
using namespace rpl::mappers;
const auto content = Ui::CreateChild<Ui::VerticalLayout>(this);
const auto info = &controller->session().data().businessInfo();
const auto session = &controller->session();
const auto info = &session->data().businessInfo();
const auto current = info->chatIntro();
_intro = info->chatIntro();
@ -471,24 +512,20 @@ void ChatIntro::setupContent(
const auto preview = content->add(
object_ptr<PreviewWrap>(
content,
&controller->session(),
IntroWithRandomSticker(&controller->session(), _intro.value())),
session,
IntroWithRandomSticker(session, _intro.value())),
{});
const auto title = content->add(
object_ptr<Ui::InputField>(
content,
st::settingsChatIntroField,
tr::lng_chat_intro_enter_title(),
current.title),
st::settingsChatIntroFieldMargins);
const auto description = content->add(
object_ptr<Ui::InputField>(
content,
st::settingsChatIntroField,
tr::lng_chat_intro_enter_message(),
current.description),
st::settingsChatIntroFieldMargins);
const auto title = AddPartInput(
content,
tr::lng_chat_intro_enter_title(),
current.title,
PartLimit(session, u"intro_title_length_limit"_q, 32));
const auto description = AddPartInput(
content,
tr::lng_chat_intro_enter_message(),
current.description,
PartLimit(session, u"intro_description_length_limit"_q, 70));
content->add(CreateIntroStickerButton(
content,
controller->uiShow(),
@ -538,6 +575,9 @@ void ChatIntro::setupContent(
}));
resetWrap->entity()->setClickedCallback([=] {
_intro = Data::ChatIntro();
title->clear();
description->clear();
title->setFocus();
});
Ui::ResizeFitChild(this, content);

View file

@ -11,6 +11,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "core/application.h"
#include "data/business/data_shortcut_messages.h"
#include "data/data_session.h"
#include "history/view/history_view_context_menu.h" // AddLengthLimitLabel.
#include "lang/lang_keys.h"
#include "main/main_account.h"
#include "main/main_session.h"
@ -211,37 +212,7 @@ void EditShortcutNameBox(
field->selectAll();
field->setMaxLength(kShortcutLimit * 2);
struct State {
rpl::variable<int> length;
};
const auto state = field->lifetime().make_state<State>();
state->length = rpl::single(
int(name.size())
) | rpl::then(field->changes() | rpl::map([=] {
return int(field->getLastText().size());
}));
const auto warning = Ui::CreateChild<Ui::FlatLabel>(
field,
state->length.value() | rpl::map([](int count) {
return (count > kShortcutLimit * 3 / 4)
? QString::number(kShortcutLimit - count)
: QString();
}),
st::editTagLimit);
state->length.value() | rpl::map(
rpl::mappers::_1 > kShortcutLimit
) | rpl::start_with_next([=](bool exceeded) {
warning->setTextColorOverride(exceeded
? st::attentionButtonFg->c
: std::optional<QColor>());
}, warning->lifetime());
rpl::combine(
field->sizeValue(),
warning->sizeValue()
) | rpl::start_with_next([=] {
warning->moveToRight(0, 0);
}, warning->lifetime());
warning->setAttribute(Qt::WA_TransparentForMouseEvents);
HistoryView::AddLengthLimitLabel(field, kShortcutLimit);
const auto callback = [=] {
const auto name = field->getLastText().trimmed();

View file

@ -641,5 +641,6 @@ settingsChatbotsDeleteIcon: icon {{ "dialogs/dialogs_cancel_search", dialogsMenu
settingsChatbotsDeleteIconOver: icon {{ "dialogs/dialogs_cancel_search", dialogsMenuIconFgOver }};
settingsChatIntroField: InputField(defaultMultiSelectSearchField) {
textMargins: margins(2px, 0px, 32px, 0px);
}
settingsChatIntroFieldMargins: margins(20px, 8px, 20px, 8px);
settingsChatIntroFieldMargins: margins(20px, 15px, 20px, 8px);