mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-06-07 15:43:55 +02:00
Added context menu to list in ChooseStarGiftRecipient.
This commit is contained in:
parent
d1898b9a0b
commit
ecac3a0f16
1 changed files with 181 additions and 26 deletions
|
@ -17,6 +17,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "base/unixtime.h"
|
#include "base/unixtime.h"
|
||||||
#include "boxes/filters/edit_filter_chats_list.h"
|
#include "boxes/filters/edit_filter_chats_list.h"
|
||||||
#include "boxes/peers/edit_peer_color_box.h"
|
#include "boxes/peers/edit_peer_color_box.h"
|
||||||
|
#include "boxes/peers/prepare_short_info_box.h"
|
||||||
#include "boxes/gift_premium_box.h"
|
#include "boxes/gift_premium_box.h"
|
||||||
#include "boxes/peer_list_controllers.h"
|
#include "boxes/peer_list_controllers.h"
|
||||||
#include "boxes/premium_preview_box.h"
|
#include "boxes/premium_preview_box.h"
|
||||||
|
@ -70,6 +71,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "ui/effects/path_shift_gradient.h"
|
#include "ui/effects/path_shift_gradient.h"
|
||||||
#include "ui/effects/premium_graphics.h"
|
#include "ui/effects/premium_graphics.h"
|
||||||
#include "ui/effects/premium_stars_colored.h"
|
#include "ui/effects/premium_stars_colored.h"
|
||||||
|
#include "ui/effects/ripple_animation.h"
|
||||||
#include "ui/layers/generic_box.h"
|
#include "ui/layers/generic_box.h"
|
||||||
#include "ui/new_badges.h"
|
#include "ui/new_badges.h"
|
||||||
#include "ui/painter.h"
|
#include "ui/painter.h"
|
||||||
|
@ -92,6 +94,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "styles/style_chat.h"
|
#include "styles/style_chat.h"
|
||||||
#include "styles/style_chat_helpers.h"
|
#include "styles/style_chat_helpers.h"
|
||||||
#include "styles/style_credits.h"
|
#include "styles/style_credits.h"
|
||||||
|
#include "styles/style_info.h"
|
||||||
#include "styles/style_layers.h"
|
#include "styles/style_layers.h"
|
||||||
#include "styles/style_menu_icons.h"
|
#include "styles/style_menu_icons.h"
|
||||||
#include "styles/style_premium.h"
|
#include "styles/style_premium.h"
|
||||||
|
@ -118,6 +121,13 @@ constexpr auto kGiftsPreloadTimeout = 3 * crl::time(1000);
|
||||||
using namespace HistoryView;
|
using namespace HistoryView;
|
||||||
using namespace Info::PeerGifts;
|
using namespace Info::PeerGifts;
|
||||||
|
|
||||||
|
enum class PickType {
|
||||||
|
Activate,
|
||||||
|
SendMessage,
|
||||||
|
OpenProfile,
|
||||||
|
};
|
||||||
|
using PickCallback = Fn<void(not_null<PeerData*>, PickType)>;
|
||||||
|
|
||||||
struct PremiumGiftsDescriptor {
|
struct PremiumGiftsDescriptor {
|
||||||
std::vector<GiftTypePremium> list;
|
std::vector<GiftTypePremium> list;
|
||||||
std::shared_ptr<Api::PremiumGiftCodeOptions> api;
|
std::shared_ptr<Api::PremiumGiftCodeOptions> api;
|
||||||
|
@ -142,6 +152,80 @@ struct GiftDetails {
|
||||||
bool byStars = false;
|
bool byStars = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class PeerRow final : public PeerListRow {
|
||||||
|
public:
|
||||||
|
using PeerListRow::PeerListRow;
|
||||||
|
|
||||||
|
QSize rightActionSize() const override;
|
||||||
|
QMargins rightActionMargins() const override;
|
||||||
|
void rightActionPaint(
|
||||||
|
Painter &p,
|
||||||
|
int x,
|
||||||
|
int y,
|
||||||
|
int outerWidth,
|
||||||
|
bool selected,
|
||||||
|
bool actionSelected) override;
|
||||||
|
|
||||||
|
void rightActionAddRipple(
|
||||||
|
QPoint point,
|
||||||
|
Fn<void()> updateCallback) override;
|
||||||
|
void rightActionStopLastRipple() override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::unique_ptr<Ui::RippleAnimation> _actionRipple;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
QSize PeerRow::rightActionSize() const {
|
||||||
|
return QSize(
|
||||||
|
st::inviteLinkThreeDotsIcon.width(),
|
||||||
|
st::inviteLinkThreeDotsIcon.height());
|
||||||
|
}
|
||||||
|
|
||||||
|
QMargins PeerRow::rightActionMargins() const {
|
||||||
|
return QMargins(
|
||||||
|
0,
|
||||||
|
(st::inviteLinkList.item.height - rightActionSize().height()) / 2,
|
||||||
|
st::inviteLinkThreeDotsSkip,
|
||||||
|
0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PeerRow::rightActionPaint(
|
||||||
|
Painter &p,
|
||||||
|
int x,
|
||||||
|
int y,
|
||||||
|
int outerWidth,
|
||||||
|
bool selected,
|
||||||
|
bool actionSelected) {
|
||||||
|
if (_actionRipple) {
|
||||||
|
_actionRipple->paint(p, x, y, outerWidth);
|
||||||
|
if (_actionRipple->empty()) {
|
||||||
|
_actionRipple.reset();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
(actionSelected
|
||||||
|
? st::inviteLinkThreeDotsIconOver
|
||||||
|
: st::inviteLinkThreeDotsIcon).paint(p, x, y, outerWidth);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PeerRow::rightActionAddRipple(QPoint point, Fn<void()> updateCallback) {
|
||||||
|
if (!_actionRipple) {
|
||||||
|
auto mask = Ui::RippleAnimation::EllipseMask(
|
||||||
|
Size(st::inviteLinkThreeDotsIcon.height()));
|
||||||
|
_actionRipple = std::make_unique<Ui::RippleAnimation>(
|
||||||
|
st::defaultRippleAnimation,
|
||||||
|
std::move(mask),
|
||||||
|
std::move(updateCallback));
|
||||||
|
}
|
||||||
|
_actionRipple->add(point);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PeerRow::rightActionStopLastRipple() {
|
||||||
|
if (_actionRipple) {
|
||||||
|
_actionRipple->lastStop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class PreviewDelegate final : public DefaultElementDelegate {
|
class PreviewDelegate final : public DefaultElementDelegate {
|
||||||
public:
|
public:
|
||||||
PreviewDelegate(
|
PreviewDelegate(
|
||||||
|
@ -2258,6 +2342,24 @@ void GiftBox(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] base::unique_qptr<Ui::PopupMenu> CreateRowContextMenu(
|
||||||
|
QWidget *parent,
|
||||||
|
not_null<PeerData*> peer,
|
||||||
|
PickCallback pick) {
|
||||||
|
auto result = base::make_unique_q<Ui::PopupMenu>(
|
||||||
|
parent,
|
||||||
|
st::popupMenuWithIcons);
|
||||||
|
result->addAction(
|
||||||
|
tr::lng_context_send_message(tr::now),
|
||||||
|
[=] { pick(peer, PickType::SendMessage); },
|
||||||
|
&st::menuIconChatBubble);
|
||||||
|
result->addAction(
|
||||||
|
tr::lng_context_view_profile(tr::now),
|
||||||
|
[=] { pick(peer, PickType::OpenProfile); },
|
||||||
|
&st::menuIconProfile);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
struct CustomList {
|
struct CustomList {
|
||||||
object_ptr<Ui::RpWidget> content = { nullptr };
|
object_ptr<Ui::RpWidget> content = { nullptr };
|
||||||
Fn<bool(int, int, int)> overrideKey;
|
Fn<bool(int, int, int)> overrideKey;
|
||||||
|
@ -2267,16 +2369,19 @@ struct CustomList {
|
||||||
|
|
||||||
class Controller final : public ContactsBoxController {
|
class Controller final : public ContactsBoxController {
|
||||||
public:
|
public:
|
||||||
Controller(
|
Controller(not_null<Main::Session*> session, PickCallback pick);
|
||||||
not_null<Main::Session*> session,
|
|
||||||
Fn<void(not_null<PeerData*>)> choose);
|
|
||||||
|
|
||||||
void noSearchSubmit();
|
void noSearchSubmit();
|
||||||
|
|
||||||
bool overrideKeyboardNavigation(
|
bool overrideKeyboardNavigation(
|
||||||
int direction,
|
int direction,
|
||||||
int fromIndex,
|
int fromIndex,
|
||||||
int toIndex) override;
|
int toIndex) override final;
|
||||||
|
|
||||||
|
void rowRightActionClicked(not_null<PeerListRow*> row) override final;
|
||||||
|
base::unique_qptr<Ui::PopupMenu> rowContextMenu(
|
||||||
|
QWidget *parent,
|
||||||
|
not_null<PeerListRow*> row) override final;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::unique_ptr<PeerListRow> createRow(
|
std::unique_ptr<PeerListRow> createRow(
|
||||||
|
@ -2285,11 +2390,13 @@ private:
|
||||||
void prepareViewHook() override;
|
void prepareViewHook() override;
|
||||||
void rowClicked(not_null<PeerListRow*> row) override;
|
void rowClicked(not_null<PeerListRow*> row) override;
|
||||||
|
|
||||||
const Fn<void(not_null<PeerData*>)> _choose;
|
const PickCallback _pick;
|
||||||
const std::vector<UserId> _contactBirthdays;
|
const std::vector<UserId> _contactBirthdays;
|
||||||
CustomList _selfOption;
|
CustomList _selfOption;
|
||||||
CustomList _birthdayOptions;
|
CustomList _birthdayOptions;
|
||||||
|
|
||||||
|
base::unique_qptr<Ui::PopupMenu> _menu;
|
||||||
|
|
||||||
bool _skipUpDirectionSelect = false;
|
bool _skipUpDirectionSelect = false;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
@ -2297,16 +2404,16 @@ private:
|
||||||
[[nodiscard]] CustomList MakeCustomList(
|
[[nodiscard]] CustomList MakeCustomList(
|
||||||
not_null<Main::Session*> session,
|
not_null<Main::Session*> session,
|
||||||
Fn<void(not_null<PeerListController*>)> fill,
|
Fn<void(not_null<PeerListController*>)> fill,
|
||||||
Fn<void(not_null<PeerData*>)> activate,
|
PickCallback pick,
|
||||||
rpl::producer<QString> below) {
|
rpl::producer<QString> below) {
|
||||||
class SelfController final : public PeerListController {
|
class CustomController final : public PeerListController {
|
||||||
public:
|
public:
|
||||||
SelfController(
|
CustomController(
|
||||||
not_null<Main::Session*> session,
|
not_null<Main::Session*> session,
|
||||||
Fn<void(not_null<PeerListController*>)> fill,
|
Fn<void(not_null<PeerListController*>)> fill,
|
||||||
Fn<void(not_null<PeerData*>)> activate)
|
PickCallback pick)
|
||||||
: _session(session)
|
: _session(session)
|
||||||
, _activate(std::move(activate))
|
, _pick(std::move(pick))
|
||||||
, _fill(std::move(fill)) {
|
, _fill(std::move(fill)) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2318,17 +2425,37 @@ private:
|
||||||
void loadMoreRows() override {
|
void loadMoreRows() override {
|
||||||
}
|
}
|
||||||
void rowClicked(not_null<PeerListRow*> row) override {
|
void rowClicked(not_null<PeerListRow*> row) override {
|
||||||
_activate(row->peer());
|
_pick(row->peer(), PickType::Activate);
|
||||||
}
|
}
|
||||||
Main::Session &session() const override {
|
Main::Session &session() const override {
|
||||||
return *_session;
|
return *_session;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void rowRightActionClicked(not_null<PeerListRow*> row) override {
|
||||||
|
delegate()->peerListShowRowMenu(row, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
base::unique_qptr<Ui::PopupMenu> rowContextMenu(
|
||||||
|
QWidget *parent,
|
||||||
|
not_null<PeerListRow*> row) override {
|
||||||
|
auto result = CreateRowContextMenu(parent, row->peer(), _pick);
|
||||||
|
|
||||||
|
if (result) {
|
||||||
|
base::take(_menu);
|
||||||
|
|
||||||
|
_menu = base::unique_qptr<Ui::PopupMenu>(result.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const not_null<Main::Session*> _session;
|
const not_null<Main::Session*> _session;
|
||||||
Fn<void(not_null<PeerData*>)> _activate;
|
PickCallback _pick;
|
||||||
Fn<void(not_null<PeerListController*>)> _fill;
|
Fn<void(not_null<PeerListController*>)> _fill;
|
||||||
|
|
||||||
|
base::unique_qptr<Ui::PopupMenu> _menu;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
auto result = object_ptr<Ui::VerticalLayout>((QWidget*)nullptr);
|
auto result = object_ptr<Ui::VerticalLayout>((QWidget*)nullptr);
|
||||||
|
@ -2340,10 +2467,10 @@ private:
|
||||||
PeerListContentDelegateSimple
|
PeerListContentDelegateSimple
|
||||||
>();
|
>();
|
||||||
const auto controller
|
const auto controller
|
||||||
= container->lifetime().make_state<SelfController>(
|
= container->lifetime().make_state<CustomController>(
|
||||||
session,
|
session,
|
||||||
fill,
|
fill,
|
||||||
activate);
|
pick);
|
||||||
|
|
||||||
controller->setStyleOverrides(&st::peerListSingleRow);
|
controller->setStyleOverrides(&st::peerListSingleRow);
|
||||||
const auto content = container->add(object_ptr<PeerListContent>(
|
const auto content = container->add(object_ptr<PeerListContent>(
|
||||||
|
@ -2392,18 +2519,18 @@ private:
|
||||||
.overrideKey = overrideKey,
|
.overrideKey = overrideKey,
|
||||||
.activate = [=] {
|
.activate = [=] {
|
||||||
if (content->hasSelection()) {
|
if (content->hasSelection()) {
|
||||||
activate(content->rowAt(content->selectedIndex())->peer());
|
pick(
|
||||||
|
content->rowAt(content->selectedIndex())->peer(),
|
||||||
|
PickType::Activate);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
.hasSelection = hasSelection,
|
.hasSelection = hasSelection,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
Controller::Controller(
|
Controller::Controller(not_null<Main::Session*> session, PickCallback pick)
|
||||||
not_null<Main::Session*> session,
|
|
||||||
Fn<void(not_null<PeerData*>)> choose)
|
|
||||||
: ContactsBoxController(session)
|
: ContactsBoxController(session)
|
||||||
, _choose(std::move(choose))
|
, _pick(std::move(pick))
|
||||||
, _contactBirthdays(
|
, _contactBirthdays(
|
||||||
session->data().knownContactBirthdays().value_or(std::vector<UserId>{}))
|
session->data().knownContactBirthdays().value_or(std::vector<UserId>{}))
|
||||||
, _selfOption(
|
, _selfOption(
|
||||||
|
@ -2415,7 +2542,7 @@ Controller::Controller(
|
||||||
controller->delegate()->peerListAppendRow(std::move(row));
|
controller->delegate()->peerListAppendRow(std::move(row));
|
||||||
controller->delegate()->peerListRefreshRows();
|
controller->delegate()->peerListRefreshRows();
|
||||||
},
|
},
|
||||||
[=](not_null<PeerData*> peer) { _choose(peer); },
|
_pick,
|
||||||
_contactBirthdays.empty()
|
_contactBirthdays.empty()
|
||||||
? tr::lng_contacts_header()
|
? tr::lng_contacts_header()
|
||||||
: tr::lng_gift_subtitle_birthdays()))
|
: tr::lng_gift_subtitle_birthdays()))
|
||||||
|
@ -2458,7 +2585,7 @@ Controller::Controller(
|
||||||
});
|
});
|
||||||
|
|
||||||
for (const auto user : usersWithBirthdays) {
|
for (const auto user : usersWithBirthdays) {
|
||||||
auto row = std::make_unique<PeerListRow>(user);
|
auto row = std::make_unique<PeerRow>(user);
|
||||||
if (auto s = status(user->birthday()); !s.isEmpty()) {
|
if (auto s = status(user->birthday()); !s.isEmpty()) {
|
||||||
row->setCustomStatus(std::move(s));
|
row->setCustomStatus(std::move(s));
|
||||||
}
|
}
|
||||||
|
@ -2467,13 +2594,34 @@ Controller::Controller(
|
||||||
|
|
||||||
controller->delegate()->peerListRefreshRows();
|
controller->delegate()->peerListRefreshRows();
|
||||||
},
|
},
|
||||||
[=](not_null<PeerData*> peer) { _choose(peer); },
|
_pick,
|
||||||
_contactBirthdays.empty()
|
_contactBirthdays.empty()
|
||||||
? rpl::producer<QString>(nullptr)
|
? rpl::producer<QString>(nullptr)
|
||||||
: tr::lng_contacts_header())) {
|
: tr::lng_contacts_header())) {
|
||||||
setStyleOverrides(&st::peerListSmallSkips);
|
setStyleOverrides(&st::peerListSmallSkips);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Controller::rowRightActionClicked(not_null<PeerListRow*> row) {
|
||||||
|
delegate()->peerListShowRowMenu(row, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
base::unique_qptr<Ui::PopupMenu> Controller::rowContextMenu(
|
||||||
|
QWidget *parent,
|
||||||
|
not_null<PeerListRow*> row) {
|
||||||
|
auto result = CreateRowContextMenu(parent, row->peer(), _pick);
|
||||||
|
|
||||||
|
if (result) {
|
||||||
|
// First clear _menu value, so that we don't check row positions yet.
|
||||||
|
base::take(_menu);
|
||||||
|
|
||||||
|
// Here unique_qptr is used like a shared pointer, where
|
||||||
|
// not the last destroyed pointer destroys the object, but the first.
|
||||||
|
_menu = base::unique_qptr<Ui::PopupMenu>(result.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
void Controller::noSearchSubmit() {
|
void Controller::noSearchSubmit() {
|
||||||
if (const auto onstack = _selfOption.activate) {
|
if (const auto onstack = _selfOption.activate) {
|
||||||
onstack();
|
onstack();
|
||||||
|
@ -2543,7 +2691,7 @@ std::unique_ptr<PeerListRow> Controller::createRow(
|
||||||
|| user->isInaccessible()) {
|
|| user->isInaccessible()) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
return ContactsBoxController::createRow(user);
|
return std::make_unique<PeerRow>(user);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Controller::prepareViewHook() {
|
void Controller::prepareViewHook() {
|
||||||
|
@ -2554,7 +2702,7 @@ void Controller::prepareViewHook() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Controller::rowClicked(not_null<PeerListRow*> row) {
|
void Controller::rowClicked(not_null<PeerListRow*> row) {
|
||||||
_choose(row->peer());
|
_pick(row->peer(), PickType::Activate);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
@ -2568,8 +2716,15 @@ void ChooseStarGiftRecipient(
|
||||||
lifetime->destroy();
|
lifetime->destroy();
|
||||||
auto controller = std::make_unique<Controller>(
|
auto controller = std::make_unique<Controller>(
|
||||||
session,
|
session,
|
||||||
[=](not_null<PeerData*> peer) {
|
[=](not_null<PeerData*> peer, PickType type) {
|
||||||
ShowStarGiftBox(window, peer);
|
if (type == PickType::Activate) {
|
||||||
|
ShowStarGiftBox(window, peer);
|
||||||
|
} else if (type == PickType::SendMessage) {
|
||||||
|
using Way = Window::SectionShow::Way;
|
||||||
|
window->showPeerHistory(peer, Way::Forward);
|
||||||
|
} else if (type == PickType::OpenProfile) {
|
||||||
|
window->show(PrepareShortInfoBox(peer, window));
|
||||||
|
}
|
||||||
});
|
});
|
||||||
const auto controllerRaw = controller.get();
|
const auto controllerRaw = controller.get();
|
||||||
auto initBox = [=](not_null<PeerListBox*> box) {
|
auto initBox = [=](not_null<PeerListBox*> box) {
|
||||||
|
|
Loading…
Add table
Reference in a new issue