Added ability to select users for awarding in giveaway box.

This commit is contained in:
23rd 2023-10-30 11:58:25 +03:00 committed by John Preston
parent 5b0c48bb52
commit 67bbb477c7
8 changed files with 253 additions and 21 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 727 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

View File

@ -10,10 +10,13 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "boxes/peers/edit_participants_box.h" // ParticipantsBoxController
#include "data/data_peer.h"
#include "data/data_user.h"
#include "info/boosts/giveaway/giveaway_type_row.h"
#include "info/info_controller.h"
#include "lang/lang_keys.h"
#include "ui/layers/generic_box.h"
#include "ui/widgets/checkbox.h"
#include "ui/widgets/labels.h"
#include "styles/style_layers.h"
namespace {
@ -28,8 +31,6 @@ public:
QWidget *parent,
not_null<PeerListRow*> row) override;
private:
};
void MembersListController::rowClicked(not_null<PeerListRow*> row) {
@ -57,25 +58,78 @@ void CreateGiveawayBox(
not_null<Ui::GenericBox*> box,
not_null<Info::Controller*> controller,
not_null<PeerData*> peer) {
box->addButton(tr::lng_box_ok(), [=] {
auto initBox = [=](not_null<PeerListBox*> peersBox) {
peersBox->setTitle(tr::lng_giveaway_award_option());
peersBox->addButton(tr::lng_settings_save(), [=] {
const auto selected = peersBox->collectSelectedRows();
peersBox->closeBox();
});
peersBox->addButton(tr::lng_cancel(), [=] {
peersBox->closeBox();
});
};
struct State final {
std::vector<not_null<PeerData*>> selectedToAward;
rpl::event_stream<> toAwardAmountChanged;
};
const auto state = box->lifetime().make_state<State>();
using GiveawayType = Giveaway::GiveawayTypeRow::Type;
using GiveawayGroup = Ui::RadioenumGroup<GiveawayType>;
const auto typeGroup = std::make_shared<GiveawayGroup>();
box->uiShow()->showBox(
Box<PeerListBox>(
std::make_unique<MembersListController>(
controller,
peer,
ParticipantsRole::Members),
std::move(initBox)),
Ui::LayerOption::KeepOther);
box->setWidth(st::boxWideWidth);
{
const auto row = box->verticalLayout()->add(
object_ptr<Giveaway::GiveawayTypeRow>(
box,
GiveawayType::Random,
tr::lng_giveaway_create_subtitle()));
row->addRadio(typeGroup);
row->setClickedCallback([=] {
typeGroup->setValue(GiveawayType::Random);
});
}
{
const auto row = box->verticalLayout()->add(
object_ptr<Giveaway::GiveawayTypeRow>(
box,
GiveawayType::SpecificUsers,
state->toAwardAmountChanged.events_starting_with(
rpl::empty_value()
) | rpl::map([=] {
const auto &selected = state->selectedToAward;
return selected.empty()
? tr::lng_giveaway_award_subtitle()
: (selected.size() == 1)
? rpl::single(selected.front()->name())
: tr::lng_giveaway_award_chosen(
lt_count,
rpl::single(selected.size()) | tr::to_count());
}) | rpl::flatten_latest()));
row->addRadio(typeGroup);
row->setClickedCallback([=] {
auto initBox = [=](not_null<PeerListBox*> peersBox) {
peersBox->setTitle(tr::lng_giveaway_award_option());
peersBox->addButton(tr::lng_settings_save(), [=] {
state->selectedToAward = peersBox->collectSelectedRows();
state->toAwardAmountChanged.fire({});
peersBox->closeBox();
});
peersBox->addButton(tr::lng_cancel(), [=] {
peersBox->closeBox();
});
peersBox->boxClosing(
) | rpl::start_with_next([=] {
typeGroup->setValue(state->selectedToAward.empty()
? GiveawayType::Random
: GiveawayType::SpecificUsers);
}, peersBox->lifetime());
};
box->uiShow()->showBox(
Box<PeerListBox>(
std::make_unique<MembersListController>(
controller,
peer,
ParticipantsRole::Members),
std::move(initBox)),
Ui::LayerOption::KeepOther);
});
}
typeGroup->setValue(GiveawayType::Random);
box->addButton(tr::lng_box_ok(), [=] {
box->closeBox();
});
}

View File

@ -0,0 +1,114 @@
/*
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/giveaway_type_row.h"
#include "lang/lang_keys.h"
#include "ui/painter.h"
#include "ui/rect.h"
#include "ui/text/text_options.h"
#include "ui/widgets/checkbox.h"
#include "styles/style_boxes.h"
#include "styles/style_statistics.h"
namespace Giveaway {
constexpr auto kColorIndexSpecific = int(4);
constexpr auto kColorIndexRandom = int(2);
GiveawayTypeRow::GiveawayTypeRow(
not_null<Ui::RpWidget*> parent,
Type type,
rpl::producer<QString> subtitle)
: RippleButton(parent, st::defaultRippleAnimation)
, _st(st::giveawayTypeListItem)
, _type(type)
, _userpic(
Ui::EmptyUserpic::UserpicColor((_type == Type::SpecificUsers)
? kColorIndexSpecific
: kColorIndexRandom),
QString())
, _name(
_st.nameStyle,
(type == Type::SpecificUsers)
? tr::lng_giveaway_award_option(tr::now)
: tr::lng_giveaway_create_option(tr::now),
Ui::NameTextOptions()) {
std::move(
subtitle
) | rpl::start_with_next([=] (const QString &s) {
_status.setText(st::defaultTextStyle, s, Ui::NameTextOptions());
}, lifetime());
}
int GiveawayTypeRow::resizeGetHeight(int) {
return _st.height;
}
void GiveawayTypeRow::paintEvent(QPaintEvent *e) {
auto p = Painter(this);
const auto paintOver = (isOver() || isDown()) && !isDisabled();
const auto skipRight = _st.photoPosition.x();
const auto outerWidth = width();
const auto isSpecific = (_type == Type::SpecificUsers);
if (paintOver) {
p.fillRect(e->rect(), _st.button.textBgOver);
}
Ui::RippleButton::paintRipple(p, 0, 0);
_userpic.paintCircle(
p,
_st.photoPosition.x(),
_st.photoPosition.y(),
outerWidth,
_st.photoSize);
{
const auto &userpic = isSpecific
? st::giveawayUserpicGroup
: st::giveawayUserpic;
const auto userpicRect = QRect(
_st.photoPosition
- QPoint(
isSpecific ? -st::giveawayUserpicSkip : 0,
isSpecific ? 0 : st::giveawayUserpicSkip),
Size(_st.photoSize));
userpic.paintInCenter(p, userpicRect);
}
const auto namex = _st.namePosition.x();
const auto namey = _st.namePosition.y();
const auto namew = outerWidth - namex - skipRight;
p.setPen(_st.nameFg);
_name.drawLeftElided(p, namex, namey, namew, width());
const auto statusx = _st.statusPosition.x();
const auto statusy = _st.statusPosition.y();
const auto statusw = outerWidth - statusx - skipRight;
p.setFont(st::contactsStatusFont);
p.setPen(isSpecific ? st::lightButtonFg : _st.statusFg);
_status.drawLeftElided(p, statusx, statusy, statusw, outerWidth);
}
void GiveawayTypeRow::addRadio(
std::shared_ptr<Ui::RadioenumGroup<Type>> typeGroup) {
const auto &st = st::defaultCheckbox;
const auto radio = Ui::CreateChild<Ui::Radioenum<Type>>(
this,
std::move(typeGroup),
_type,
QString(),
st);
radio->moveToLeft(
st::giveawayRadioPosition.x(),
st::giveawayRadioPosition.y());
radio->setAttribute(Qt::WA_TransparentForMouseEvents);
radio->show();
}
} // namespace Giveaway

View File

@ -0,0 +1,49 @@
/*
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
#include "ui/empty_userpic.h"
#include "ui/widgets/buttons.h"
namespace Ui {
template <typename Enum>
class RadioenumGroup;
} // namespace Ui
namespace Giveaway {
class GiveawayTypeRow final : public Ui::RippleButton {
public:
enum class Type {
Random,
SpecificUsers,
};
GiveawayTypeRow(
not_null<Ui::RpWidget*> parent,
Type type,
rpl::producer<QString> subtitle);
void addRadio(std::shared_ptr<Ui::RadioenumGroup<Type>> typeGroup);
protected:
void paintEvent(QPaintEvent *e) override;
int resizeGetHeight(int) override;
private:
const style::PeerListItem _st;
const Type _type;
Ui::EmptyUserpic _userpic;
Ui::Text::String _status;
Ui::Text::String _name;
};
} // namespace Giveaway

View File

@ -148,3 +148,15 @@ getBoostsButton: SettingsButton(reportReasonButton) {
textFgOver: lightButtonFg;
}
getBoostsButtonIcon: icon {{ "menu/gift_premium", lightButtonFg }};
giveawayTypeListItem: PeerListItem(defaultPeerListItem) {
height: 52px;
photoPosition: point(58px, 6px);
namePosition: point(110px, 8px);
statusPosition: point(110px, 28px);
photoSize: 42px;
}
giveawayUserpic: icon {{ "boosts/filled_gift", windowFgActive }};
giveawayUserpicSkip: 1px;
giveawayUserpicGroup: icon {{ "limits/groups", windowFgActive }};
giveawayRadioPosition: point(21px, 16px);

View File

@ -109,6 +109,9 @@ PRIVATE
info/userpic/info_userpic_emoji_builder_layer.cpp
info/userpic/info_userpic_emoji_builder_layer.h
info/boosts/giveaway/giveaway_type_row.cpp
info/boosts/giveaway/giveaway_type_row.h
layout/abstract_layout_item.cpp
layout/abstract_layout_item.h
layout/layout_mosaic.cpp