diff --git a/Telegram/Resources/icons/poll/filled/filled_poll_country.svg b/Telegram/Resources/icons/poll/filled/filled_poll_country.svg
new file mode 100644
index 0000000000..bf77eb160f
--- /dev/null
+++ b/Telegram/Resources/icons/poll/filled/filled_poll_country.svg
@@ -0,0 +1,13 @@
+
+
diff --git a/Telegram/Resources/langs/lang.strings b/Telegram/Resources/langs/lang.strings
index 4af5e88359..e9b9151bd1 100644
--- a/Telegram/Resources/langs/lang.strings
+++ b/Telegram/Resources/langs/lang.strings
@@ -6997,6 +6997,12 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_polls_create_hide_results_about" = "If you switch this on, results will appear only after the poll closes.";
"lng_polls_create_restrict_to_subscribers" = "Restrict to Subscribers";
"lng_polls_create_restrict_to_subscribers_about" = "Only subscribers who joined 24+ hours ago can vote.";
+"lng_polls_create_limit_by_country" = "Limit by Country";
+"lng_polls_create_limit_by_country_about" = "Only users from selected countries can vote.";
+"lng_polls_create_allowed_countries" = "Allowed Countries";
+"lng_polls_create_countries_count#one" = "{count} country";
+"lng_polls_create_countries_count#other" = "{count} countries";
+"lng_polls_create_choose_country" = "Please choose at least one country.";
"lng_polls_create_duration_custom" = "Custom";
"lng_polls_create_deadline_title" = "Deadline";
"lng_polls_create_deadline_button" = "Set Deadline";
diff --git a/Telegram/SourceFiles/boxes/create_poll_box.cpp b/Telegram/SourceFiles/boxes/create_poll_box.cpp
index 5266267e82..5dc27e963e 100644
--- a/Telegram/SourceFiles/boxes/create_poll_box.cpp
+++ b/Telegram/SourceFiles/boxes/create_poll_box.cpp
@@ -15,6 +15,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "base/event_filter.h"
#include "base/random.h"
#include "base/unique_qptr.h"
+#include "countries/countries_instance.h"
#include "chat_helpers/emoji_suggestions_widget.h"
#include "chat_helpers/message_field.h"
#include "chat_helpers/tabbed_panel.h"
@@ -38,6 +39,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "data/stickers/data_custom_emoji.h"
#include "history/view/media/menu/history_view_poll_menu.h"
#include "history/view/history_view_schedule_box.h"
+#include "info/channel_statistics/boosts/giveaway/select_countries_box.h"
#include "lang/lang_keys.h"
#include "layout/layout_document_generic_preview.h"
#include "main/main_app_config.h"
@@ -1458,6 +1460,7 @@ object_ptr CreatePollBox::setupContent() {
rpl::event_stream showWhoVotedForceOn;
rpl::variable closePeriod = 0;
rpl::variable closeDate = TimeId(0);
+ rpl::variable> countriesValue;
std::shared_ptr descriptionMedia
= std::make_shared();
std::shared_ptr solutionMedia
@@ -2745,6 +2748,68 @@ object_ptr CreatePollBox::setupContent() {
rpl::single(!!(_chosen & PollData::Flag::SubscribersOnly)),
st::detailedSettingsButtonStyle).get()
: nullptr;
+ const auto limitByCountry = isBroadcastChannel
+ ? AddPollToggleButton(
+ container,
+ tr::lng_polls_create_limit_by_country(),
+ tr::lng_polls_create_limit_by_country_about(),
+ {
+ .icon = &st::pollBoxFilledPollCountryIcon,
+ .background = &st::settingsIconBg6,
+ },
+ rpl::single(false),
+ st::detailedSettingsButtonStyle).get()
+ : nullptr;
+ const auto countriesWrap = limitByCountry
+ ? container->add(
+ object_ptr>(
+ container,
+ object_ptr(container)))
+ : nullptr;
+ const auto countriesButton = [=] {
+ if (!countriesWrap) {
+ return (Ui::SettingsButton*)(nullptr);
+ }
+ const auto inner = countriesWrap->entity();
+ return AddButtonWithLabel(
+ inner,
+ tr::lng_polls_create_allowed_countries(),
+ state->countriesValue.value(
+ ) | rpl::map([=](const std::vector &countries) {
+ if (countries.empty()) {
+ return QString();
+ }
+ if (countries.size() == 1) {
+ return Countries::Instance().countryNameByISO2(
+ countries.front());
+ }
+ return tr::lng_polls_create_countries_count(
+ tr::now,
+ lt_count,
+ countries.size());
+ }),
+ st::settingsButtonNoIcon).get();
+ }();
+ if (countriesWrap) {
+ countriesWrap->toggleOn(
+ rpl::single(limitByCountry->toggled())
+ | rpl::then(limitByCountry->toggledChanges()));
+ }
+ if (countriesButton) {
+ countriesButton->setClickedCallback([=] {
+ const auto done = [=](std::vector countries) {
+ state->countriesValue = std::move(countries);
+ };
+ const auto checkError = [](int) {
+ return false;
+ };
+ show->show(Box(
+ Ui::SelectCountriesBox,
+ state->countriesValue.current(),
+ done,
+ checkError));
+ });
+ }
const auto solution = setupSolution(
container,
@@ -2879,6 +2944,10 @@ object_ptr CreatePollBox::setupContent() {
&& restrictToSubscribers->toggled());
const auto hideResultsEnabled = duration->toggled()
&& hideResults->toggled();
+ result.countries = (limitByCountry
+ && limitByCountry->toggled())
+ ? state->countriesValue.current()
+ : std::vector();
result.setFlags(Flag(0)
| (publicVotes ? Flag::PublicVotes : Flag(0))
| (multiChoice ? Flag::MultiChoice : Flag(0))
@@ -2950,6 +3019,13 @@ object_ptr CreatePollBox::setupContent() {
} else {
state->error &= ~Error::Deadline;
}
+ if (limitByCountry
+ && limitByCountry->toggled()
+ && state->countriesValue.current().empty()) {
+ state->error |= Error::Country;
+ } else {
+ state->error &= ~Error::Country;
+ }
};
const auto showError = [show = uiShow()](
tr::phrase<> text) {
@@ -3009,6 +3085,11 @@ object_ptr CreatePollBox::setupContent() {
ShowMediaUploadingToast();
} else if (state->error & Error::Deadline) {
showError(tr::lng_polls_create_deadline_expired);
+ } else if (state->error & Error::Country) {
+ showError(tr::lng_polls_create_choose_country);
+ if (countriesButton) {
+ scrollToWidget(countriesButton);
+ }
} else if (!state->error) {
auto result = collectResult();
result.options = sendOptions;
@@ -3068,6 +3149,12 @@ object_ptr CreatePollBox::setupContent() {
if (restrictToSubscribers) {
restrictToSubscribers->finishAnimating();
}
+ if (limitByCountry) {
+ limitByCountry->finishAnimating();
+ }
+ if (countriesWrap) {
+ countriesWrap->finishAnimating();
+ }
return result;
}
diff --git a/Telegram/SourceFiles/boxes/create_poll_box.h b/Telegram/SourceFiles/boxes/create_poll_box.h
index 6940101697..1bd2518200 100644
--- a/Telegram/SourceFiles/boxes/create_poll_box.h
+++ b/Telegram/SourceFiles/boxes/create_poll_box.h
@@ -68,6 +68,7 @@ private:
Solution = 0x10,
Media = 0x20,
Deadline = 0x40,
+ Country = 0x80,
};
friend constexpr inline bool is_flag_type(Error) { return true; }
using Errors = base::flags;
diff --git a/Telegram/SourceFiles/boxes/polls.style b/Telegram/SourceFiles/boxes/polls.style
index c1846047b2..f5f07922fa 100644
--- a/Telegram/SourceFiles/boxes/polls.style
+++ b/Telegram/SourceFiles/boxes/polls.style
@@ -137,6 +137,7 @@ pollBoxFilledPollRevoteIcon: icon{{ "poll/filled/filled_poll_revote", activeButt
pollBoxFilledPollShuffleIcon: icon{{ "poll/filled/filled_poll_shuffle", activeButtonFg }};
pollBoxFilledPollMultipleIcon: icon{{ "poll/filled/filled_poll_multiple", activeButtonFg }};
pollBoxFilledPollSubscribersIcon: icon{{ "poll/filled/filled_poll_subscribers-20x20", activeButtonFg }};
+pollBoxFilledPollCountryIcon: icon{{ "poll/filled/filled_poll_country-20x20", activeButtonFg }};
pollAttachTextSkip: 28px;
pollAttachProgressMargin: 4px;
diff --git a/Telegram/SourceFiles/data/data_poll.cpp b/Telegram/SourceFiles/data/data_poll.cpp
index 583377f3bf..23e046aa54 100644
--- a/Telegram/SourceFiles/data/data_poll.cpp
+++ b/Telegram/SourceFiles/data/data_poll.cpp
@@ -109,6 +109,13 @@ bool PollData::applyChanges(const MTPDpoll &poll) {
| (poll.is_subscribers_only() ? Flag::SubscribersOnly : Flag(0));
const auto newCloseDate = poll.vclose_date().value_or_empty();
const auto newClosePeriod = poll.vclose_period().value_or_empty();
+ auto newCountries = std::vector();
+ if (const auto countries = poll.vcountries_iso2()) {
+ newCountries.reserve(countries->v.size());
+ for (const auto &country : countries->v) {
+ newCountries.push_back(qs(country));
+ }
+ }
auto newAnswers = ranges::views::all(
poll.vanswers().v
) | ranges::views::transform([&](const MTPPollAnswer &data) {
@@ -146,6 +153,7 @@ bool PollData::applyChanges(const MTPDpoll &poll) {
const auto changed1 = (question != newQuestion)
|| (closeDate != newCloseDate)
|| (closePeriod != newClosePeriod)
+ || (countries != newCountries)
|| (_flags != newFlags);
const auto changed2 = (answers != newAnswers);
if (!changed1 && !changed2) {
@@ -155,6 +163,7 @@ bool PollData::applyChanges(const MTPDpoll &poll) {
question = newQuestion;
closeDate = newCloseDate;
closePeriod = newClosePeriod;
+ countries = std::move(newCountries);
_flags = newFlags;
}
if (changed2) {
@@ -410,6 +419,13 @@ QString PollData::debugString() const {
if (!solution.text.isEmpty()) {
result += u"Solution: "_q + solution.text + u'\n';
}
+ if (!countries.empty()) {
+ result += u"Countries: "_q + countries.front();
+ for (auto i = 1, count = int(countries.size()); i != count; ++i) {
+ result += u", "_q + countries[i];
+ }
+ result += u'\n';
+ }
return result;
}
@@ -528,6 +544,11 @@ MTPPoll PollDataToMTP(not_null poll, bool close) {
poll->answers,
ranges::back_inserter(answers),
convert);
+ auto countries = QVector();
+ countries.reserve(poll->countries.size());
+ for (const auto &country : poll->countries) {
+ countries.push_back(MTP_string(country));
+ }
using Flag = MTPDpoll::Flag;
const auto flags = ((poll->closed() || close) ? Flag::f_closed : Flag(0))
| (poll->multiChoice() ? Flag::f_multiple_choice : Flag(0))
@@ -541,7 +562,8 @@ MTPPoll PollDataToMTP(not_null poll, bool close) {
: Flag(0))
| (poll->subscribersOnly() ? Flag::f_subscribers_only : Flag(0))
| (poll->closePeriod > 0 ? Flag::f_close_period : Flag(0))
- | (poll->closeDate > 0 ? Flag::f_close_date : Flag(0));
+ | (poll->closeDate > 0 ? Flag::f_close_date : Flag(0))
+ | (countries.isEmpty() ? Flag(0) : Flag::f_countries_iso2);
return MTP_poll(
MTP_long(poll->id),
MTP_flags(flags),
@@ -551,7 +573,7 @@ MTPPoll PollDataToMTP(not_null poll, bool close) {
MTP_vector(answers),
MTP_int(poll->closePeriod),
MTP_int(poll->closeDate),
- MTP_vector(), // countries_iso2
+ MTP_vector(std::move(countries)), // countries_iso2
MTP_long(0));
}
diff --git a/Telegram/SourceFiles/data/data_poll.h b/Telegram/SourceFiles/data/data_poll.h
index cbc7d3713b..d3059639ce 100644
--- a/Telegram/SourceFiles/data/data_poll.h
+++ b/Telegram/SourceFiles/data/data_poll.h
@@ -114,6 +114,7 @@ struct PollData {
TextWithEntities solution;
PollMedia attachedMedia;
PollMedia solutionMedia;
+ std::vector countries;
TimeId closePeriod = 0;
TimeId closeDate = 0;
int totalVoters = 0;