mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-06-05 06:33:57 +02:00
Send paid reactions from channels.
This commit is contained in:
parent
79ce24222a
commit
ba84499f00
6 changed files with 175 additions and 38 deletions
|
@ -73,6 +73,17 @@ const std::vector<SendAsPeer> &SendAsPeers::list(
|
||||||
return (i != end(_lists)) ? i->second : _onlyMe;
|
return (i != end(_lists)) ? i->second : _onlyMe;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::vector<not_null<PeerData*>> SendAsPeers::paidReactionList() const {
|
||||||
|
auto result = std::vector<not_null<PeerData*>>();
|
||||||
|
const auto owner = &_session->data();
|
||||||
|
owner->enumerateBroadcasts([&](not_null<ChannelData*> channel) {
|
||||||
|
if (channel->amCreator() && !ranges::contains(result, channel)) {
|
||||||
|
result.push_back(channel);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
rpl::producer<not_null<PeerData*>> SendAsPeers::updated() const {
|
rpl::producer<not_null<PeerData*>> SendAsPeers::updated() const {
|
||||||
return _updates.events();
|
return _updates.events();
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,6 +34,8 @@ public:
|
||||||
void setChosen(not_null<PeerData*> peer, PeerId chosenId);
|
void setChosen(not_null<PeerData*> peer, PeerId chosenId);
|
||||||
[[nodiscard]] PeerId chosen(not_null<PeerData*> peer) const;
|
[[nodiscard]] PeerId chosen(not_null<PeerData*> peer) const;
|
||||||
|
|
||||||
|
[[nodiscard]] std::vector<not_null<PeerData*>> paidReactionList() const;
|
||||||
|
|
||||||
// If !list(peer).empty() then the result will be from that list.
|
// If !list(peer).empty() then the result will be from that list.
|
||||||
[[nodiscard]] not_null<PeerData*> resolveChosen(
|
[[nodiscard]] not_null<PeerData*> resolveChosen(
|
||||||
not_null<PeerData*> peer) const;
|
not_null<PeerData*> peer) const;
|
||||||
|
|
|
@ -22,6 +22,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "history/history_item.h"
|
#include "history/history_item.h"
|
||||||
#include "lang/lang_keys.h"
|
#include "lang/lang_keys.h"
|
||||||
#include "main/session/session_show.h"
|
#include "main/session/session_show.h"
|
||||||
|
#include "main/session/send_as_peers.h"
|
||||||
#include "main/main_app_config.h"
|
#include "main/main_app_config.h"
|
||||||
#include "main/main_session.h"
|
#include "main/main_session.h"
|
||||||
#include "payments/ui/payments_reaction_box.h"
|
#include "payments/ui/payments_reaction_box.h"
|
||||||
|
@ -206,35 +207,46 @@ void ShowPaidReactionDetails(
|
||||||
.photo = (peer
|
.photo = (peer
|
||||||
? Ui::MakeUserpicThumbnail(peer)
|
? Ui::MakeUserpicThumbnail(peer)
|
||||||
: Ui::MakeHiddenAuthorThumbnail()),
|
: Ui::MakeHiddenAuthorThumbnail()),
|
||||||
|
.barePeerId = peer ? uint64(peer->id.value) : 0,
|
||||||
.count = int(entry.count),
|
.count = int(entry.count),
|
||||||
.click = peer ? open : Fn<void()>(),
|
.click = peer ? open : Fn<void()>(),
|
||||||
.my = (entry.my == 1),
|
.my = (entry.my == 1),
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
const auto channels = session->sendAsPeers().paidReactionList();
|
||||||
const auto topPaid = item->topPaidReactionsWithLocal();
|
const auto topPaid = item->topPaidReactionsWithLocal();
|
||||||
top.reserve(topPaid.size() + 2);
|
top.reserve(topPaid.size() + 2 + channels.size());
|
||||||
for (const auto &entry : topPaid) {
|
for (const auto &entry : topPaid) {
|
||||||
add(entry);
|
add(entry);
|
||||||
if (entry.my) {
|
|
||||||
auto copy = entry;
|
|
||||||
copy.peer = entry.peer ? nullptr : session->user().get();
|
|
||||||
add(copy);
|
|
||||||
}
|
}
|
||||||
|
auto myAdded = base::flat_set<uint64>();
|
||||||
|
const auto i = ranges::find(top, true, &Ui::PaidReactionTop::my);
|
||||||
|
if (i != end(top)) {
|
||||||
|
myAdded.emplace(i->barePeerId);
|
||||||
}
|
}
|
||||||
if (!ranges::contains(top, true, &Ui::PaidReactionTop::my)) {
|
const auto myCount = uint32((i != end(top)) ? i->count : 0);
|
||||||
auto entry = Data::MessageReactionsTopPaid{
|
const auto myAdd = [&](PeerData *peer) {
|
||||||
.peer = session->user(),
|
const auto barePeerId = peer ? uint64(peer->id.value) : 0;
|
||||||
.count = 0,
|
if (!myAdded.emplace(barePeerId).second) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
add(Data::MessageReactionsTopPaid{
|
||||||
|
.peer = peer,
|
||||||
|
.count = myCount,
|
||||||
.my = true,
|
.my = true,
|
||||||
|
});
|
||||||
};
|
};
|
||||||
add(entry);
|
const auto globalPrivacy = &session->api().globalPrivacy();
|
||||||
entry.peer = nullptr;
|
const auto shown = globalPrivacy->paidReactionShownPeerCurrent();
|
||||||
add(entry);
|
const auto owner = &session->data();
|
||||||
if (session->api().globalPrivacy().paidReactionShownPeerCurrent()) {
|
const auto shownPeer = shown ? owner->peer(shown).get() : nullptr;
|
||||||
std::swap(top.front(), top.back());
|
myAdd(shownPeer);
|
||||||
|
myAdd(session->user());
|
||||||
|
myAdd(nullptr);
|
||||||
|
for (const auto &channel : channels) {
|
||||||
|
myAdd(channel);
|
||||||
}
|
}
|
||||||
}
|
ranges::stable_sort(top, ranges::greater(), &Ui::PaidReactionTop::count);
|
||||||
ranges::sort(top, ranges::greater(), &Ui::PaidReactionTop::count);
|
|
||||||
|
|
||||||
const auto linked = item->discussionPostOriginalSender();
|
const auto linked = item->discussionPostOriginalSender();
|
||||||
const auto channel = (linked ? linked : item->history()->peer.get());
|
const auto channel = (linked ? linked : item->history()->peer.get());
|
||||||
|
@ -245,8 +257,8 @@ void ShowPaidReactionDetails(
|
||||||
.channel = channel->name(),
|
.channel = channel->name(),
|
||||||
.submit = std::move(submitText),
|
.submit = std::move(submitText),
|
||||||
.balanceValue = session->credits().balanceValue(),
|
.balanceValue = session->credits().balanceValue(),
|
||||||
.send = [=](int count, bool anonymous) {
|
.send = [=](int count, uint64 barePeerId) {
|
||||||
send(count, anonymous ? PeerId() : 0, send);
|
send(count, PeerId(barePeerId), send);
|
||||||
},
|
},
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
|
|
@ -10,19 +10,23 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "base/qt/qt_compare.h"
|
#include "base/qt/qt_compare.h"
|
||||||
#include "lang/lang_keys.h"
|
#include "lang/lang_keys.h"
|
||||||
#include "ui/boxes/boost_box.h" // MakeBoostFeaturesBadge.
|
#include "ui/boxes/boost_box.h" // MakeBoostFeaturesBadge.
|
||||||
|
#include "ui/controls/who_reacted_context_action.h"
|
||||||
#include "ui/effects/premium_bubble.h"
|
#include "ui/effects/premium_bubble.h"
|
||||||
#include "ui/layers/generic_box.h"
|
#include "ui/layers/generic_box.h"
|
||||||
#include "ui/text/text_utilities.h"
|
#include "ui/text/text_utilities.h"
|
||||||
#include "ui/widgets/buttons.h"
|
#include "ui/widgets/buttons.h"
|
||||||
#include "ui/widgets/checkbox.h"
|
#include "ui/widgets/checkbox.h"
|
||||||
#include "ui/widgets/continuous_sliders.h"
|
#include "ui/widgets/continuous_sliders.h"
|
||||||
|
#include "ui/widgets/popup_menu.h"
|
||||||
#include "ui/wrap/slide_wrap.h"
|
#include "ui/wrap/slide_wrap.h"
|
||||||
#include "ui/dynamic_image.h"
|
#include "ui/dynamic_image.h"
|
||||||
#include "ui/painter.h"
|
#include "ui/painter.h"
|
||||||
#include "ui/vertical_list.h"
|
#include "ui/vertical_list.h"
|
||||||
#include "styles/style_chat.h"
|
#include "styles/style_chat.h"
|
||||||
|
#include "styles/style_chat_helpers.h"
|
||||||
#include "styles/style_credits.h"
|
#include "styles/style_credits.h"
|
||||||
#include "styles/style_layers.h"
|
#include "styles/style_layers.h"
|
||||||
|
#include "styles/style_media_player.h"
|
||||||
#include "styles/style_premium.h"
|
#include "styles/style_premium.h"
|
||||||
#include "styles/style_settings.h"
|
#include "styles/style_settings.h"
|
||||||
|
|
||||||
|
@ -192,13 +196,41 @@ void PaidReactionSlider(
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AddArrowDown(not_null<RpWidget*> widget) {
|
||||||
|
const auto arrow = CreateChild<RpWidget>(widget);
|
||||||
|
const auto icon = &st::paidReactChannelArrow;
|
||||||
|
const auto skip = st::lineWidth * 4;
|
||||||
|
const auto size = icon->width() + skip * 2;
|
||||||
|
arrow->resize(size, size);
|
||||||
|
widget->widthValue() | rpl::start_with_next([=](int width) {
|
||||||
|
const auto left = (width - st::paidReactTopUserpic) / 2;
|
||||||
|
arrow->moveToRight(left - skip, -st::lineWidth, width);
|
||||||
|
}, widget->lifetime());
|
||||||
|
arrow->paintRequest() | rpl::start_with_next([=] {
|
||||||
|
Painter p(arrow);
|
||||||
|
auto hq = PainterHighQualityEnabler(p);
|
||||||
|
p.setBrush(st::activeButtonBg);
|
||||||
|
p.setPen(st::activeButtonFg);
|
||||||
|
const auto rect = arrow->rect();
|
||||||
|
const auto line = st::lineWidth;
|
||||||
|
p.drawEllipse(rect.marginsRemoved({ line, line, line, line }));
|
||||||
|
icon->paint(p, skip, (size - icon->height()) / 2 + line, size);
|
||||||
|
}, widget->lifetime());
|
||||||
|
arrow->setAttribute(Qt::WA_TransparentForMouseEvents);
|
||||||
|
arrow->show();
|
||||||
|
}
|
||||||
|
|
||||||
[[nodiscard]] not_null<RpWidget*> MakeTopReactor(
|
[[nodiscard]] not_null<RpWidget*> MakeTopReactor(
|
||||||
not_null<QWidget*> parent,
|
not_null<QWidget*> parent,
|
||||||
const PaidReactionTop &data) {
|
const PaidReactionTop &data,
|
||||||
|
Fn<void()> selectShownPeer) {
|
||||||
const auto result = CreateChild<AbstractButton>(parent);
|
const auto result = CreateChild<AbstractButton>(parent);
|
||||||
result->show();
|
result->show();
|
||||||
if (data.click && !data.my) {
|
if (data.click && !data.my) {
|
||||||
result->setClickedCallback(data.click);
|
result->setClickedCallback(data.click);
|
||||||
|
} else if (data.click && selectShownPeer) {
|
||||||
|
result->setClickedCallback(selectShownPeer);
|
||||||
|
AddArrowDown(result);
|
||||||
} else {
|
} else {
|
||||||
result->setAttribute(Qt::WA_TransparentForMouseEvents);
|
result->setAttribute(Qt::WA_TransparentForMouseEvents);
|
||||||
}
|
}
|
||||||
|
@ -244,11 +276,60 @@ void PaidReactionSlider(
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SelectShownPeer(
|
||||||
|
std::shared_ptr<QPointer<PopupMenu>> menu,
|
||||||
|
not_null<QWidget*> parent,
|
||||||
|
const std::vector<PaidReactionTop> &mine,
|
||||||
|
uint64 selected,
|
||||||
|
Fn<void(uint64)> callback) {
|
||||||
|
if (*menu) {
|
||||||
|
(*menu)->hideMenu();
|
||||||
|
}
|
||||||
|
(*menu) = CreateChild<PopupMenu>(
|
||||||
|
parent,
|
||||||
|
st::paidReactChannelMenu);
|
||||||
|
|
||||||
|
struct Entry {
|
||||||
|
not_null<Ui::WhoReactedEntryAction*> action;
|
||||||
|
std::shared_ptr<Ui::DynamicImage> userpic;
|
||||||
|
};
|
||||||
|
auto actions = std::make_shared<std::vector<Entry>>();
|
||||||
|
actions->reserve(mine.size());
|
||||||
|
for (const auto &entry : mine) {
|
||||||
|
auto action = base::make_unique_q<WhoReactedEntryAction>(
|
||||||
|
(*menu)->menu(),
|
||||||
|
nullptr,
|
||||||
|
(*menu)->menu()->st(),
|
||||||
|
Ui::WhoReactedEntryData());
|
||||||
|
const auto index = int(actions->size());
|
||||||
|
actions->push_back({ action.get(), entry.photo->clone() });
|
||||||
|
const auto id = entry.barePeerId;
|
||||||
|
const auto updateUserpic = [=] {
|
||||||
|
const auto size = st::defaultWhoRead.photoSize;
|
||||||
|
actions->at(index).action->setData({
|
||||||
|
.text = entry.name,
|
||||||
|
.type = ((id == selected)
|
||||||
|
? Ui::WhoReactedType::RefRecipientNow
|
||||||
|
: Ui::WhoReactedType::RefRecipient),
|
||||||
|
.userpic = actions->at(index).userpic->image(size),
|
||||||
|
.callback = [=] { callback(id); },
|
||||||
|
});
|
||||||
|
};
|
||||||
|
actions->back().userpic->subscribeToUpdates(updateUserpic);
|
||||||
|
|
||||||
|
(*menu)->addAction(std::move(action));
|
||||||
|
updateUserpic();
|
||||||
|
}
|
||||||
|
(*menu)->popup(QCursor::pos());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
void FillTopReactors(
|
void FillTopReactors(
|
||||||
not_null<VerticalLayout*> container,
|
not_null<VerticalLayout*> container,
|
||||||
std::vector<PaidReactionTop> top,
|
std::vector<PaidReactionTop> top,
|
||||||
rpl::producer<int> chosen,
|
rpl::producer<int> chosen,
|
||||||
rpl::producer<bool> anonymous) {
|
rpl::producer<uint64> shownPeer,
|
||||||
|
Fn<void(uint64)> changeShownPeer) {
|
||||||
container->add(
|
container->add(
|
||||||
MakeBoostFeaturesBadge(
|
MakeBoostFeaturesBadge(
|
||||||
container,
|
container,
|
||||||
|
@ -272,28 +353,33 @@ void FillTopReactors(
|
||||||
bool chosenChanged = false;
|
bool chosenChanged = false;
|
||||||
};
|
};
|
||||||
const auto state = wrap->lifetime().make_state<State>();
|
const auto state = wrap->lifetime().make_state<State>();
|
||||||
|
const auto menu = std::make_shared<QPointer<Ui::PopupMenu>>();
|
||||||
|
|
||||||
rpl::combine(
|
rpl::combine(
|
||||||
std::move(chosen),
|
std::move(chosen),
|
||||||
std::move(anonymous)
|
std::move(shownPeer)
|
||||||
) | rpl::start_with_next([=](int chosen, bool anonymous) {
|
) | rpl::start_with_next([=](int chosen, uint64 barePeerId) {
|
||||||
if (!state->initialChosen) {
|
if (!state->initialChosen) {
|
||||||
state->initialChosen = chosen;
|
state->initialChosen = chosen;
|
||||||
} else if (*state->initialChosen != chosen) {
|
} else if (*state->initialChosen != chosen) {
|
||||||
state->chosenChanged = true;
|
state->chosenChanged = true;
|
||||||
}
|
}
|
||||||
|
auto mine = std::vector<PaidReactionTop>();
|
||||||
auto list = std::vector<PaidReactionTop>();
|
auto list = std::vector<PaidReactionTop>();
|
||||||
list.reserve(kMaxTopPaidShown + 1);
|
list.reserve(kMaxTopPaidShown + 1);
|
||||||
for (const auto &entry : top) {
|
for (const auto &entry : top) {
|
||||||
if (!entry.my) {
|
if (!entry.my) {
|
||||||
list.push_back(entry);
|
list.push_back(entry);
|
||||||
} else if (!entry.click == anonymous) {
|
} else if (entry.barePeerId == barePeerId) {
|
||||||
auto copy = entry;
|
auto copy = entry;
|
||||||
if (state->chosenChanged) {
|
if (state->chosenChanged) {
|
||||||
copy.count += chosen;
|
copy.count += chosen;
|
||||||
}
|
}
|
||||||
list.push_back(copy);
|
list.push_back(copy);
|
||||||
}
|
}
|
||||||
|
if (entry.my && entry.barePeerId) {
|
||||||
|
mine.push_back(entry);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
ranges::stable_sort(
|
ranges::stable_sort(
|
||||||
list,
|
list,
|
||||||
|
@ -303,6 +389,14 @@ void FillTopReactors(
|
||||||
|| (!list.empty() && !list.back().count)) {
|
|| (!list.empty() && !list.back().count)) {
|
||||||
list.pop_back();
|
list.pop_back();
|
||||||
}
|
}
|
||||||
|
auto selectShownPeer = (mine.size() < 2)
|
||||||
|
? Fn<void()>()
|
||||||
|
: [=] { SelectShownPeer(
|
||||||
|
menu,
|
||||||
|
parent,
|
||||||
|
mine,
|
||||||
|
barePeerId,
|
||||||
|
changeShownPeer); };
|
||||||
if (list.empty()) {
|
if (list.empty()) {
|
||||||
wrap->hide(anim::type::normal);
|
wrap->hide(anim::type::normal);
|
||||||
} else {
|
} else {
|
||||||
|
@ -319,7 +413,7 @@ void FillTopReactors(
|
||||||
const auto i = state->cache.find(key);
|
const auto i = state->cache.find(key);
|
||||||
const auto widget = (i != end(state->cache))
|
const auto widget = (i != end(state->cache))
|
||||||
? i->second
|
? i->second
|
||||||
: MakeTopReactor(parent, entry);
|
: MakeTopReactor(parent, entry, selectShownPeer);
|
||||||
state->widgets.push_back(widget);
|
state->widgets.push_back(widget);
|
||||||
widget->show();
|
widget->show();
|
||||||
}
|
}
|
||||||
|
@ -368,7 +462,8 @@ void PaidReactionsBox(
|
||||||
|
|
||||||
struct State {
|
struct State {
|
||||||
rpl::variable<int> chosen;
|
rpl::variable<int> chosen;
|
||||||
rpl::variable<bool> anonymous;
|
rpl::variable<uint64> shownPeer;
|
||||||
|
uint64 savedShownPeer = 0;
|
||||||
};
|
};
|
||||||
const auto state = box->lifetime().make_state<State>();
|
const auto state = box->lifetime().make_state<State>();
|
||||||
|
|
||||||
|
@ -377,12 +472,16 @@ void PaidReactionsBox(
|
||||||
state->chosen = count;
|
state->chosen = count;
|
||||||
};
|
};
|
||||||
|
|
||||||
const auto initialAnonymous = ranges::find(
|
const auto initialShownPeer = ranges::find(
|
||||||
args.top,
|
args.top,
|
||||||
true,
|
true,
|
||||||
&PaidReactionTop::my
|
&PaidReactionTop::my
|
||||||
)->click == nullptr;
|
)->barePeerId;
|
||||||
state->anonymous = initialAnonymous;
|
state->shownPeer = initialShownPeer;
|
||||||
|
state->savedShownPeer = ranges::find_if(args.top, [](
|
||||||
|
const PaidReactionTop &entry) {
|
||||||
|
return entry.my && entry.barePeerId != 0;
|
||||||
|
})->barePeerId;
|
||||||
|
|
||||||
const auto content = box->verticalLayout();
|
const auto content = box->verticalLayout();
|
||||||
AddSkip(content, st::boxTitleClose.height + st::paidReactBubbleTop);
|
AddSkip(content, st::boxTitleClose.height + st::paidReactBubbleTop);
|
||||||
|
@ -455,25 +554,30 @@ void PaidReactionsBox(
|
||||||
content,
|
content,
|
||||||
std::move(args.top),
|
std::move(args.top),
|
||||||
state->chosen.value(),
|
state->chosen.value(),
|
||||||
state->anonymous.value());
|
state->shownPeer.value(),
|
||||||
|
[=](uint64 barePeerId) {
|
||||||
|
state->shownPeer = state->savedShownPeer = barePeerId;
|
||||||
|
});
|
||||||
|
|
||||||
const auto named = box->addRow(object_ptr<CenterWrap<Checkbox>>(
|
const auto named = box->addRow(object_ptr<CenterWrap<Checkbox>>(
|
||||||
box,
|
box,
|
||||||
object_ptr<Checkbox>(
|
object_ptr<Checkbox>(
|
||||||
box,
|
box,
|
||||||
tr::lng_paid_react_show_in_top(tr::now),
|
tr::lng_paid_react_show_in_top(tr::now),
|
||||||
!state->anonymous.current())));
|
state->shownPeer.current() != 0)));
|
||||||
state->anonymous = named->entity()->checkedValue(
|
named->entity()->checkedValue(
|
||||||
) | rpl::map(!rpl::mappers::_1);
|
) | rpl::start_with_next([=](bool show) {
|
||||||
|
state->shownPeer = show ? state->savedShownPeer : 0;
|
||||||
|
}, named->lifetime());
|
||||||
|
|
||||||
const auto button = box->addButton(rpl::single(QString()), [=] {
|
const auto button = box->addButton(rpl::single(QString()), [=] {
|
||||||
args.send(state->chosen.current(), !named->entity()->checked());
|
args.send(state->chosen.current(), state->shownPeer.current());
|
||||||
});
|
});
|
||||||
|
|
||||||
box->boxClosing() | rpl::filter([=] {
|
box->boxClosing() | rpl::filter([=] {
|
||||||
return state->anonymous.current() != initialAnonymous;
|
return state->shownPeer.current() != initialShownPeer;
|
||||||
}) | rpl::start_with_next([=] {
|
}) | rpl::start_with_next([=] {
|
||||||
args.send(0, state->anonymous.current());
|
args.send(0, state->shownPeer.current());
|
||||||
}, box->lifetime());
|
}, box->lifetime());
|
||||||
|
|
||||||
{
|
{
|
||||||
|
|
|
@ -23,6 +23,7 @@ struct TextWithContext {
|
||||||
struct PaidReactionTop {
|
struct PaidReactionTop {
|
||||||
QString name;
|
QString name;
|
||||||
std::shared_ptr<DynamicImage> photo;
|
std::shared_ptr<DynamicImage> photo;
|
||||||
|
uint64 barePeerId = 0;
|
||||||
int count = 0;
|
int count = 0;
|
||||||
Fn<void()> click;
|
Fn<void()> click;
|
||||||
bool my = false;
|
bool my = false;
|
||||||
|
@ -37,7 +38,7 @@ struct PaidReactionBoxArgs {
|
||||||
QString channel;
|
QString channel;
|
||||||
Fn<rpl::producer<TextWithContext>(rpl::producer<int> amount)> submit;
|
Fn<rpl::producer<TextWithContext>(rpl::producer<int> amount)> submit;
|
||||||
rpl::producer<StarsAmount> balanceValue;
|
rpl::producer<StarsAmount> balanceValue;
|
||||||
Fn<void(int, bool)> send;
|
Fn<void(int, uint64)> send;
|
||||||
};
|
};
|
||||||
|
|
||||||
void PaidReactionsBox(
|
void PaidReactionsBox(
|
||||||
|
|
|
@ -401,6 +401,13 @@ paidReactToastLabel: FlatLabel(defaultFlatLabel) {
|
||||||
paidReactTopStarIcon: icon{{ "chat/mini_stars", premiumButtonFg }};
|
paidReactTopStarIcon: icon{{ "chat/mini_stars", premiumButtonFg }};
|
||||||
paidReactTopStarIconPosition: point(0px, 1px);
|
paidReactTopStarIconPosition: point(0px, 1px);
|
||||||
paidReactTopStarSkip: 4px;
|
paidReactTopStarSkip: 4px;
|
||||||
|
paidReactChannelArrow: icon{{ "intro_country_dropdown", activeButtonFg }};
|
||||||
|
paidReactChannelMenu: PopupMenu(popupMenuWithIcons) {
|
||||||
|
menu: Menu(menuWithIcons) {
|
||||||
|
widthMax: 240px;
|
||||||
|
}
|
||||||
|
maxHeight: 345px;
|
||||||
|
}
|
||||||
|
|
||||||
toastUndoStroke: 2px;
|
toastUndoStroke: 2px;
|
||||||
toastUndoSpace: 8px;
|
toastUndoSpace: 8px;
|
||||||
|
|
Loading…
Add table
Reference in a new issue