mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-06-05 06:33:57 +02:00
Added box for selecting countries.
This commit is contained in:
parent
af03660cab
commit
2d097ca9ae
4 changed files with 254 additions and 0 deletions
|
@ -0,0 +1,227 @@
|
||||||
|
/*
|
||||||
|
This file is part of Telegram Desktop,
|
||||||
|
the official desktop application for the Telegram messaging service.
|
||||||
|
|
||||||
|
For license and copyright information please follow this link:
|
||||||
|
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
|
*/
|
||||||
|
#include "info/boosts/giveaway/select_countries_box.h"
|
||||||
|
|
||||||
|
#include "countries/countries_instance.h"
|
||||||
|
#include "lang/lang_keys.h"
|
||||||
|
#include "ui/emoji_config.h"
|
||||||
|
#include "ui/layers/generic_box.h"
|
||||||
|
#include "ui/painter.h"
|
||||||
|
#include "ui/rect.h"
|
||||||
|
#include "ui/widgets/buttons.h"
|
||||||
|
#include "ui/widgets/checkbox.h"
|
||||||
|
#include "ui/widgets/labels.h"
|
||||||
|
#include "ui/widgets/multi_select.h"
|
||||||
|
#include "ui/wrap/slide_wrap.h"
|
||||||
|
#include "styles/style_boxes.h"
|
||||||
|
#include "styles/style_giveaway.h"
|
||||||
|
#include "styles/style_settings.h"
|
||||||
|
|
||||||
|
namespace Ui {
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
void AddSkip(not_null<Ui::VerticalLayout*> container) {
|
||||||
|
container->add(object_ptr<Ui::FixedHeightWidget>(
|
||||||
|
container,
|
||||||
|
st::settingsSectionSkip));
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] QImage CacheFlagEmoji(const QString &flag) {
|
||||||
|
const auto &st = st::giveawayGiftCodeCountrySelect.item;
|
||||||
|
auto roundPaintCache = QImage(
|
||||||
|
Size(st.height) * style::DevicePixelRatio(),
|
||||||
|
QImage::Format_ARGB32_Premultiplied);
|
||||||
|
roundPaintCache.setDevicePixelRatio(style::DevicePixelRatio());
|
||||||
|
roundPaintCache.fill(Qt::transparent);
|
||||||
|
{
|
||||||
|
const auto size = st.height;
|
||||||
|
auto p = Painter(&roundPaintCache);
|
||||||
|
auto hq = PainterHighQualityEnabler(p);
|
||||||
|
const auto flagText = Ui::Text::String(st::defaultTextStyle, flag);
|
||||||
|
p.setPen(st.textBg);
|
||||||
|
p.setBrush(st.textBg);
|
||||||
|
p.drawEllipse(0, 0, size, size);
|
||||||
|
flagText.draw(p, {
|
||||||
|
.position = QPoint(
|
||||||
|
0 + (size - flagText.maxWidth()) / 2,
|
||||||
|
0 + (size - flagText.minHeight()) / 2),
|
||||||
|
.outerWidth = size,
|
||||||
|
.availableWidth = size,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return roundPaintCache;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
void SelectCountriesBox(
|
||||||
|
not_null<Ui::GenericBox*> box,
|
||||||
|
const std::vector<QString> &selected,
|
||||||
|
Fn<void(std::vector<QString>)> doneCallback,
|
||||||
|
Fn<bool(int)> checkErrorCallback) {
|
||||||
|
struct State final {
|
||||||
|
std::vector<QString> resultList;
|
||||||
|
};
|
||||||
|
const auto state = box->lifetime().make_state<State>();
|
||||||
|
|
||||||
|
const auto multiSelect = box->setPinnedToTopContent(
|
||||||
|
object_ptr<Ui::MultiSelect>(
|
||||||
|
box,
|
||||||
|
st::giveawayGiftCodeCountrySelect,
|
||||||
|
tr::lng_participant_filter()));
|
||||||
|
AddSkip(box->verticalLayout());
|
||||||
|
const auto &buttonSt = st::giveawayGiftCodeCountryButton;
|
||||||
|
|
||||||
|
struct Entry final {
|
||||||
|
Ui::SlideWrap<Ui::SettingsButton> *wrap = nullptr;
|
||||||
|
QStringList list;
|
||||||
|
QString iso2;
|
||||||
|
};
|
||||||
|
|
||||||
|
auto countries = Countries::Instance().list();
|
||||||
|
ranges::sort(countries, [](
|
||||||
|
const Countries::Info &a,
|
||||||
|
const Countries::Info &b) {
|
||||||
|
return (a.name.compare(b.name, Qt::CaseInsensitive) < 0);
|
||||||
|
});
|
||||||
|
auto buttons = std::vector<Entry>();
|
||||||
|
buttons.reserve(countries.size());
|
||||||
|
for (const auto &country : countries) {
|
||||||
|
const auto flag = Countries::Instance().flagEmojiByISO2(country.iso2);
|
||||||
|
const auto asd = Ui::Emoji::Find(flag);
|
||||||
|
if (!Ui::Emoji::Find(flag)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
const auto itemId = buttons.size();
|
||||||
|
auto button = object_ptr<SettingsButton>(
|
||||||
|
box->verticalLayout(),
|
||||||
|
rpl::single(flag + ' ' + country.name),
|
||||||
|
buttonSt);
|
||||||
|
const auto radio = Ui::CreateChild<Ui::RpWidget>(button.data());
|
||||||
|
const auto radioView = std::make_shared<Ui::RadioView>(
|
||||||
|
st::defaultRadio,
|
||||||
|
false,
|
||||||
|
[=] { radio->update(); });
|
||||||
|
|
||||||
|
{
|
||||||
|
const auto radioSize = radioView->getSize();
|
||||||
|
radio->resize(radioSize);
|
||||||
|
radio->paintRequest(
|
||||||
|
) | rpl::start_with_next([=](const QRect &r) {
|
||||||
|
auto p = QPainter(radio);
|
||||||
|
radioView->paint(p, 0, 0, radioSize.width());
|
||||||
|
}, radio->lifetime());
|
||||||
|
const auto buttonHeight = buttonSt.height
|
||||||
|
+ rect::m::sum::v(buttonSt.padding);
|
||||||
|
radio->moveToLeft(
|
||||||
|
st::giveawayRadioPosition.x(),
|
||||||
|
(buttonHeight - radioSize.height()) / 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto roundPaintCache = CacheFlagEmoji(flag);
|
||||||
|
const auto paintCallback = [=](Painter &p, int x, int y, int, int) {
|
||||||
|
p.drawImage(x, y, roundPaintCache);
|
||||||
|
};
|
||||||
|
const auto choose = [=](bool clicked) {
|
||||||
|
const auto value = !radioView->checked();
|
||||||
|
if (value && checkErrorCallback(state->resultList.size())) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
radioView->setChecked(value, anim::type::normal);
|
||||||
|
|
||||||
|
if (value) {
|
||||||
|
state->resultList.push_back(country.iso2);
|
||||||
|
multiSelect->addItem(
|
||||||
|
itemId,
|
||||||
|
country.name,
|
||||||
|
st::activeButtonBg,
|
||||||
|
paintCallback,
|
||||||
|
clicked
|
||||||
|
? Ui::MultiSelect::AddItemWay::Default
|
||||||
|
: Ui::MultiSelect::AddItemWay::SkipAnimation);
|
||||||
|
} else {
|
||||||
|
auto &list = state->resultList;
|
||||||
|
list.erase(ranges::remove(list, country.iso2), end(list));
|
||||||
|
multiSelect->removeItem(itemId);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
button->setClickedCallback([=] {
|
||||||
|
choose(true);
|
||||||
|
});
|
||||||
|
if (ranges::contains(selected, country.iso2)) {
|
||||||
|
choose(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto wrap = box->verticalLayout()->add(
|
||||||
|
object_ptr<Ui::SlideWrap<Ui::SettingsButton>>(
|
||||||
|
box,
|
||||||
|
std::move(button)));
|
||||||
|
wrap->toggle(true, anim::type::instant);
|
||||||
|
|
||||||
|
{
|
||||||
|
auto list = QStringList{
|
||||||
|
flag,
|
||||||
|
country.name,
|
||||||
|
country.alternativeName,
|
||||||
|
};
|
||||||
|
buttons.push_back({ wrap, std::move(list), country.iso2 });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto noResults = box->addRow(
|
||||||
|
object_ptr<Ui::SlideWrap<Ui::VerticalLayout>>(
|
||||||
|
box,
|
||||||
|
object_ptr<Ui::VerticalLayout>(box)));
|
||||||
|
{
|
||||||
|
noResults->toggle(false, anim::type::instant);
|
||||||
|
const auto container = noResults->entity();
|
||||||
|
AddSkip(container);
|
||||||
|
AddSkip(container);
|
||||||
|
container->add(
|
||||||
|
object_ptr<Ui::CenterWrap<Ui::FlatLabel>>(
|
||||||
|
container,
|
||||||
|
object_ptr<Ui::FlatLabel>(
|
||||||
|
container,
|
||||||
|
tr::lng_search_messages_none(),
|
||||||
|
st::membersAbout)));
|
||||||
|
AddSkip(container);
|
||||||
|
AddSkip(container);
|
||||||
|
}
|
||||||
|
|
||||||
|
multiSelect->setQueryChangedCallback([=](const QString &query) {
|
||||||
|
auto wasAnyFound = false;
|
||||||
|
for (const auto &entry : buttons) {
|
||||||
|
const auto found = ranges::any_of(entry.list, [&](
|
||||||
|
const QString &s) {
|
||||||
|
return s.startsWith(query, Qt::CaseInsensitive);
|
||||||
|
});
|
||||||
|
entry.wrap->toggle(found, anim::type::instant);
|
||||||
|
wasAnyFound |= found;
|
||||||
|
}
|
||||||
|
noResults->toggle(!wasAnyFound, anim::type::instant);
|
||||||
|
});
|
||||||
|
multiSelect->setItemRemovedCallback([=](uint64 itemId) {
|
||||||
|
auto &list = state->resultList;
|
||||||
|
auto &button = buttons[itemId];
|
||||||
|
const auto it = ranges::find(list, button.iso2);
|
||||||
|
if (it != end(list)) {
|
||||||
|
list.erase(it);
|
||||||
|
button.wrap->entity()->clicked({}, Qt::LeftButton);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
box->addButton(tr::lng_settings_save(), [=] {
|
||||||
|
doneCallback(state->resultList);
|
||||||
|
box->closeBox();
|
||||||
|
});
|
||||||
|
box->addButton(tr::lng_cancel(), [=] {
|
||||||
|
box->closeBox();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Ui
|
|
@ -0,0 +1,20 @@
|
||||||
|
/*
|
||||||
|
This file is part of Telegram Desktop,
|
||||||
|
the official desktop application for the Telegram messaging service.
|
||||||
|
|
||||||
|
For license and copyright information please follow this link:
|
||||||
|
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace Ui {
|
||||||
|
|
||||||
|
class GenericBox;
|
||||||
|
|
||||||
|
void SelectCountriesBox(
|
||||||
|
not_null<Ui::GenericBox*> box,
|
||||||
|
const std::vector<QString> &selected,
|
||||||
|
Fn<void(std::vector<QString>)> doneCallback,
|
||||||
|
Fn<bool(int)> checkErrorCallback);
|
||||||
|
|
||||||
|
} // namespace Ui
|
|
@ -160,3 +160,8 @@ giveawayUserpic: icon {{ "boosts/filled_gift", windowFgActive }};
|
||||||
giveawayUserpicSkip: 1px;
|
giveawayUserpicSkip: 1px;
|
||||||
giveawayUserpicGroup: icon {{ "limits/groups", windowFgActive }};
|
giveawayUserpicGroup: icon {{ "limits/groups", windowFgActive }};
|
||||||
giveawayRadioPosition: point(21px, 16px);
|
giveawayRadioPosition: point(21px, 16px);
|
||||||
|
|
||||||
|
giveawayGiftCodeCountryButton: SettingsButton(reportReasonButton) {
|
||||||
|
}
|
||||||
|
giveawayGiftCodeCountrySelect: MultiSelect(defaultMultiSelect) {
|
||||||
|
}
|
||||||
|
|
|
@ -111,6 +111,8 @@ PRIVATE
|
||||||
|
|
||||||
info/boosts/giveaway/giveaway_type_row.cpp
|
info/boosts/giveaway/giveaway_type_row.cpp
|
||||||
info/boosts/giveaway/giveaway_type_row.h
|
info/boosts/giveaway/giveaway_type_row.h
|
||||||
|
info/boosts/giveaway/select_countries_box.cpp
|
||||||
|
info/boosts/giveaway/select_countries_box.h
|
||||||
|
|
||||||
layout/abstract_layout_item.cpp
|
layout/abstract_layout_item.cpp
|
||||||
layout/abstract_layout_item.h
|
layout/abstract_layout_item.h
|
||||||
|
|
Loading…
Add table
Reference in a new issue