mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2026-08-06 11:52:58 +00:00
Added country-based poll restrictions with selectable allowed countries
This commit is contained in:
@@ -0,0 +1,13 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="72px" height="72px" viewBox="0 0 72 72" version="1.1" xmlns="http://www.w3.org/2000/svg">
|
||||
<title>Filled / filled_poll_country</title>
|
||||
<defs>
|
||||
<linearGradient id="filled_poll_country_gradient" x1="0%" y1="0%" x2="0%" y2="100%">
|
||||
<stop offset="0%" stop-color="#0BC4BA"/>
|
||||
<stop offset="100%" stop-color="#1196E4"/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
<g id="Filled-/-filled_poll_country" stroke="none" fill="none" fill-rule="evenodd">
|
||||
<path d="M36,9.33333333 C24.8,9.33333333 14.6666667,17.92 14.6666667,31.2 C14.6666667,39.68 21.2,51.7866667 34.24,63.28 C35.2533333,64.16 36.7733333,64.16 37.7866667,63.28 C50.8,51.7866667 57.3333333,39.68 57.3333333,31.2 C57.3333333,17.92 47.2,9.33333333 36,9.33333333 Z M36,37 C32.15,37 29,33.85 29,30 C29,26.15 32.15,23 36,23 C39.85,23 43,26.15 43,30 C43,33.85 39.85,37 36,37 Z" id="Shape" fill="url(#filled_poll_country_gradient)"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 988 B |
@@ -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";
|
||||
|
||||
@@ -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<Ui::RpWidget> CreatePollBox::setupContent() {
|
||||
rpl::event_stream<bool> showWhoVotedForceOn;
|
||||
rpl::variable<int> closePeriod = 0;
|
||||
rpl::variable<TimeId> closeDate = TimeId(0);
|
||||
rpl::variable<std::vector<QString>> countriesValue;
|
||||
std::shared_ptr<PollMediaState> descriptionMedia
|
||||
= std::make_shared<PollMediaState>();
|
||||
std::shared_ptr<PollMediaState> solutionMedia
|
||||
@@ -2745,6 +2748,68 @@ object_ptr<Ui::RpWidget> 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<Ui::SlideWrap<Ui::VerticalLayout>>(
|
||||
container,
|
||||
object_ptr<Ui::VerticalLayout>(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<QString> &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<QString> 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<Ui::RpWidget> CreatePollBox::setupContent() {
|
||||
&& restrictToSubscribers->toggled());
|
||||
const auto hideResultsEnabled = duration->toggled()
|
||||
&& hideResults->toggled();
|
||||
result.countries = (limitByCountry
|
||||
&& limitByCountry->toggled())
|
||||
? state->countriesValue.current()
|
||||
: std::vector<QString>();
|
||||
result.setFlags(Flag(0)
|
||||
| (publicVotes ? Flag::PublicVotes : Flag(0))
|
||||
| (multiChoice ? Flag::MultiChoice : Flag(0))
|
||||
@@ -2950,6 +3019,13 @@ object_ptr<Ui::RpWidget> 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<Ui::RpWidget> 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<Ui::RpWidget> CreatePollBox::setupContent() {
|
||||
if (restrictToSubscribers) {
|
||||
restrictToSubscribers->finishAnimating();
|
||||
}
|
||||
if (limitByCountry) {
|
||||
limitByCountry->finishAnimating();
|
||||
}
|
||||
if (countriesWrap) {
|
||||
countriesWrap->finishAnimating();
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -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<Error>;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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<QString>();
|
||||
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<const PollData*> poll, bool close) {
|
||||
poll->answers,
|
||||
ranges::back_inserter(answers),
|
||||
convert);
|
||||
auto countries = QVector<MTPstring>();
|
||||
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<const PollData*> 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<const PollData*> poll, bool close) {
|
||||
MTP_vector<MTPPollAnswer>(answers),
|
||||
MTP_int(poll->closePeriod),
|
||||
MTP_int(poll->closeDate),
|
||||
MTP_vector<MTPstring>(), // countries_iso2
|
||||
MTP_vector<MTPstring>(std::move(countries)), // countries_iso2
|
||||
MTP_long(0));
|
||||
}
|
||||
|
||||
|
||||
@@ -114,6 +114,7 @@ struct PollData {
|
||||
TextWithEntities solution;
|
||||
PollMedia attachedMedia;
|
||||
PollMedia solutionMedia;
|
||||
std::vector<QString> countries;
|
||||
TimeId closePeriod = 0;
|
||||
TimeId closeDate = 0;
|
||||
int totalVoters = 0;
|
||||
|
||||
Reference in New Issue
Block a user