[poll-create] Added poll description.

This commit is contained in:
23rd
2026-03-17 10:28:31 +03:00
parent 546c786ed3
commit 9e482556ea
7 changed files with 83 additions and 14 deletions
+1
View File
@@ -6845,6 +6845,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_polls_create_title" = "New poll";
"lng_polls_create_question" = "Question";
"lng_polls_create_question_placeholder" = "Ask a question";
"lng_polls_create_description_placeholder" = "Add Description (optional)";
"lng_polls_create_options" = "Poll options";
"lng_polls_create_option_add" = "Add an option...";
"lng_polls_create_limit#one" = "You can add {count} more option.";
+11 -2
View File
@@ -8,6 +8,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "api/api_polls.h"
#include "api/api_common.h"
#include "api/api_text_entities.h"
#include "api/api_updates.h"
#include "apiwrap.h"
#include "base/random.h"
@@ -30,6 +31,7 @@ Polls::Polls(not_null<ApiWrap*> api)
void Polls::create(
const PollData &data,
const TextWithEntities &text,
SendAction action,
Fn<void()> done,
Fn<void()> fail) {
@@ -82,6 +84,13 @@ void Polls::create(
if (sendAs) {
sendFlags |= MTPmessages_SendMedia::Flag::f_send_as;
}
auto sentEntities = Api::EntitiesToMTP(
_session,
text.entities,
Api::ConvertOption::SkipLocal);
if (!sentEntities.v.isEmpty()) {
sendFlags |= MTPmessages_SendMedia::Flag::f_entities;
}
auto &histories = history->owner().histories();
const auto randomId = base::RandomValue<uint64>();
histories.sendPreparedMessage(
@@ -93,10 +102,10 @@ void Polls::create(
peer->input(),
Data::Histories::ReplyToPlaceholder(),
PollDataToInputMedia(&data),
MTP_string(),
MTP_string(text.text),
MTP_long(randomId),
MTPReplyMarkup(),
MTPVector<MTPMessageEntity>(),
sentEntities,
MTP_int(action.options.scheduled),
MTP_int(action.options.scheduleRepeatPeriod),
(sendAs ? sendAs->input() : MTP_inputPeerEmpty()),
+2
View File
@@ -8,6 +8,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#pragma once
#include "mtproto/sender.h"
#include "ui/text/text_entity.h"
class ApiWrap;
class HistoryItem;
@@ -27,6 +28,7 @@ public:
void create(
const PollData &data,
const TextWithEntities &text,
SendAction action,
Fn<void()> done,
Fn<void()> fail);
+45 -5
View File
@@ -947,6 +947,21 @@ not_null<Ui::InputField*> CreatePollBox::setupQuestion(
return question;
}
not_null<Ui::InputField*> CreatePollBox::setupDescription(
not_null<Ui::VerticalLayout*> container) {
const auto session = &_controller->session();
const auto description = container->add(
object_ptr<Ui::InputField>(
container,
st::pollDescriptionField,
Ui::InputField::Mode::MultiLine,
tr::lng_polls_create_description_placeholder()),
st::pollDescriptionFieldPadding);
InitField(getDelegate()->outerContainer(), description, session);
description->setSubmitSettings(Ui::InputField::SubmitSettings::Both);
return description;
}
not_null<Ui::InputField*> CreatePollBox::setupSolution(
not_null<Ui::VerticalLayout*> container,
rpl::producer<bool> shown) {
@@ -1036,6 +1051,7 @@ object_ptr<Ui::RpWidget> CreatePollBox::setupContent() {
const auto container = result.data();
const auto question = setupQuestion(container);
const auto description = setupDescription(container);
Ui::AddDivider(container);
Ui::AddSkip(container);
container->add(
@@ -1074,10 +1090,16 @@ object_ptr<Ui::RpWidget> CreatePollBox::setupContent() {
question->tabbed(
) | rpl::on_next([=](not_null<bool*> handled) {
options->focusFirst();
description->setFocus();
*handled = true;
}, question->lifetime());
description->tabbed(
) | rpl::on_next([=](not_null<bool*> handled) {
options->focusFirst();
*handled = true;
}, description->lifetime());
Ui::AddSkip(container);
Ui::AddSubsectionTitle(container, tr::lng_polls_create_settings());
@@ -1221,16 +1243,22 @@ object_ptr<Ui::RpWidget> CreatePollBox::setupContent() {
question->submits(
) | rpl::on_next([=] {
if (isValidQuestion()) {
options->focusFirst();
description->setFocus();
}
}, question->lifetime());
description->submits(
) | rpl::on_next([=] {
options->focusFirst();
}, description->lifetime());
_setInnerFocus = [=] {
question->setFocusFast();
};
const auto collectResult = [=] {
const auto textWithTags = question->getTextWithTags();
const auto descriptionWithTags = description->getTextWithTags();
using Flag = PollData::Flag;
auto result = PollData(&_controller->session().data(), id);
result.question.text = textWithTags.text;
@@ -1254,7 +1282,17 @@ object_ptr<Ui::RpWidget> CreatePollBox::setupContent() {
| (!revoting->toggled() ? Flag::RevotingDisabled : Flag(0))
| (shuffle->toggled() ? Flag::ShuffleAnswers : Flag(0))
| (quiz->toggled() ? Flag::Quiz : Flag(0)));
return result;
auto text = TextWithEntities{
descriptionWithTags.text,
TextUtilities::ConvertTextTagsToEntities(
descriptionWithTags.tags),
};
TextUtilities::Trim(text);
return Result{
std::move(result),
std::move(text),
Api::SendOptions(),
};
};
const auto collectError = [=] {
if (isValidQuestion()) {
@@ -1298,7 +1336,9 @@ object_ptr<Ui::RpWidget> CreatePollBox::setupContent() {
} else if (state->error & Error::Solution) {
solution->showError();
} else if (!state->error) {
_submitRequests.fire({ collectResult(), sendOptions });
auto result = collectResult();
result.options = sendOptions;
_submitRequests.fire(std::move(result));
}
};
const auto sendAction = SendMenu::DefaultCallback(
@@ -1312,7 +1352,7 @@ object_ptr<Ui::RpWidget> CreatePollBox::setupContent() {
options->backspaceInFront(
) | rpl::on_next([=] {
FocusAtEnd(question);
FocusAtEnd(description);
}, lifetime());
const auto isNormal = (_sendType == Api::SendType::Normal);
@@ -34,6 +34,7 @@ class CreatePollBox : public Ui::BoxContent {
public:
struct Result {
PollData poll;
TextWithEntities text;
Api::SendOptions options;
};
@@ -68,6 +69,8 @@ private:
[[nodiscard]] object_ptr<Ui::RpWidget> setupContent();
[[nodiscard]] not_null<Ui::InputField*> setupQuestion(
not_null<Ui::VerticalLayout*> container);
[[nodiscard]] not_null<Ui::InputField*> setupDescription(
not_null<Ui::VerticalLayout*> container);
[[nodiscard]] not_null<Ui::InputField*> setupSolution(
not_null<Ui::VerticalLayout*> container,
rpl::producer<bool> shown);
+9
View File
@@ -24,3 +24,12 @@ pollBoxFilledPollRevoteIcon: icon{{ "poll/filled/filled_poll_revote", activeButt
pollBoxFilledPollShuffleIcon: icon{{ "poll/filled/filled_poll_shuffle", activeButtonFg }};
pollBoxFilledChatlistMentionIcon: icon{{ "poll/filled/filled_chatlist_mention", activeButtonFg }};
pollBoxFilledPollMultipleIcon: icon{{ "poll/filled/filled_poll_multiple", activeButtonFg }};
pollAttachTextSkip: 28px;
pollDescriptionFieldPadding: margins(22px, 5px, 11px, 5px);
pollDescriptionField: InputField(createPollField) {
textMargins: margins(0px, 4px, pollAttachTextSkip, 4px);
border: 0px;
borderActive: 0px;
}
@@ -2259,13 +2259,18 @@ void PeerMenuCreatePoll(
action.clearDraft = false;
}
const auto api = &peer->session().api();
api->polls().create(result.poll, action, crl::guard(weak, [=] {
state->create = nullptr;
weak->closeBox();
}), crl::guard(weak, [=] {
state->lock = false;
weak->submitFailed(tr::lng_attach_failed(tr::now));
}));
api->polls().create(
result.poll,
result.text,
action,
crl::guard(weak, [=] {
state->create = nullptr;
weak->closeBox();
}),
crl::guard(weak, [=] {
state->lock = false;
weak->submitFailed(tr::lng_attach_failed(tr::now));
}));
};
box->submitRequests(
) | rpl::on_next(state->create, box->lifetime());