diff --git a/Telegram/Resources/langs/lang.strings b/Telegram/Resources/langs/lang.strings index c9b83ffd3b..414d59ca41 100644 --- a/Telegram/Resources/langs/lang.strings +++ b/Telegram/Resources/langs/lang.strings @@ -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."; diff --git a/Telegram/SourceFiles/api/api_polls.cpp b/Telegram/SourceFiles/api/api_polls.cpp index 2aa18ad9e9..b80c408fe6 100644 --- a/Telegram/SourceFiles/api/api_polls.cpp +++ b/Telegram/SourceFiles/api/api_polls.cpp @@ -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 api) void Polls::create( const PollData &data, + const TextWithEntities &text, SendAction action, Fn done, Fn 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(); 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(), + sentEntities, MTP_int(action.options.scheduled), MTP_int(action.options.scheduleRepeatPeriod), (sendAs ? sendAs->input() : MTP_inputPeerEmpty()), diff --git a/Telegram/SourceFiles/api/api_polls.h b/Telegram/SourceFiles/api/api_polls.h index f77e34d67c..e5b1f2487a 100644 --- a/Telegram/SourceFiles/api/api_polls.h +++ b/Telegram/SourceFiles/api/api_polls.h @@ -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 done, Fn fail); diff --git a/Telegram/SourceFiles/boxes/create_poll_box.cpp b/Telegram/SourceFiles/boxes/create_poll_box.cpp index 693ca76078..a7283d8962 100644 --- a/Telegram/SourceFiles/boxes/create_poll_box.cpp +++ b/Telegram/SourceFiles/boxes/create_poll_box.cpp @@ -947,6 +947,21 @@ not_null CreatePollBox::setupQuestion( return question; } +not_null CreatePollBox::setupDescription( + not_null container) { + const auto session = &_controller->session(); + const auto description = container->add( + object_ptr( + 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 CreatePollBox::setupSolution( not_null container, rpl::producer shown) { @@ -1036,6 +1051,7 @@ object_ptr 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 CreatePollBox::setupContent() { question->tabbed( ) | rpl::on_next([=](not_null handled) { - options->focusFirst(); + description->setFocus(); *handled = true; }, question->lifetime()); + description->tabbed( + ) | rpl::on_next([=](not_null handled) { + options->focusFirst(); + *handled = true; + }, description->lifetime()); + Ui::AddSkip(container); Ui::AddSubsectionTitle(container, tr::lng_polls_create_settings()); @@ -1221,16 +1243,22 @@ object_ptr 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 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 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 CreatePollBox::setupContent() { options->backspaceInFront( ) | rpl::on_next([=] { - FocusAtEnd(question); + FocusAtEnd(description); }, lifetime()); const auto isNormal = (_sendType == Api::SendType::Normal); diff --git a/Telegram/SourceFiles/boxes/create_poll_box.h b/Telegram/SourceFiles/boxes/create_poll_box.h index 33fbdd3f1e..42f07259b0 100644 --- a/Telegram/SourceFiles/boxes/create_poll_box.h +++ b/Telegram/SourceFiles/boxes/create_poll_box.h @@ -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 setupContent(); [[nodiscard]] not_null setupQuestion( not_null container); + [[nodiscard]] not_null setupDescription( + not_null container); [[nodiscard]] not_null setupSolution( not_null container, rpl::producer shown); diff --git a/Telegram/SourceFiles/boxes/polls.style b/Telegram/SourceFiles/boxes/polls.style index 070e1e1765..b4f9f57140 100644 --- a/Telegram/SourceFiles/boxes/polls.style +++ b/Telegram/SourceFiles/boxes/polls.style @@ -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; +} diff --git a/Telegram/SourceFiles/window/window_peer_menu.cpp b/Telegram/SourceFiles/window/window_peer_menu.cpp index 92e4d27a64..0dc7d4477c 100644 --- a/Telegram/SourceFiles/window/window_peer_menu.cpp +++ b/Telegram/SourceFiles/window/window_peer_menu.cpp @@ -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());