mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-04-16 14:17:12 +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;
|
||||
giveawayUserpicGroup: icon {{ "limits/groups", windowFgActive }};
|
||||
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.h
|
||||
info/boosts/giveaway/select_countries_box.cpp
|
||||
info/boosts/giveaway/select_countries_box.h
|
||||
|
||||
layout/abstract_layout_item.cpp
|
||||
layout/abstract_layout_item.h
|
||||
|
|
Loading…
Add table
Reference in a new issue