Display full list of requests.
This commit is contained in:
parent
ab58aa020e
commit
9dfbc96274
|
@ -991,3 +991,16 @@ sponsoredUrlButton: RoundButton(defaultActiveButton) {
|
||||||
color: windowBgOver;
|
color: windowBgOver;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
requestsBoxItem: PeerListItem(peerListBoxItem) {
|
||||||
|
height: 99px;
|
||||||
|
}
|
||||||
|
requestsBoxList: PeerList(peerListBox) {
|
||||||
|
item: requestsBoxItem;
|
||||||
|
}
|
||||||
|
requestsAcceptButton: RoundButton(defaultActiveButton) {
|
||||||
|
}
|
||||||
|
requestsRejectButton: RoundButton(defaultLightButton) {
|
||||||
|
}
|
||||||
|
requestAcceptPosition: point(71px, 58px);
|
||||||
|
requestButtonsSkip: 9px;
|
||||||
|
|
|
@ -519,6 +519,10 @@ void PeerListRow::refreshName(const style::PeerListItem &st) {
|
||||||
_name.setText(st.nameStyle, text, Ui::NameTextOptions());
|
_name.setText(st.nameStyle, text, Ui::NameTextOptions());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int PeerListRow::elementsCount() const {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
QRect PeerListRow::elementGeometry(int element, int outerWidth) const {
|
QRect PeerListRow::elementGeometry(int element, int outerWidth) const {
|
||||||
if (element != 1) {
|
if (element != 1) {
|
||||||
return QRect();
|
return QRect();
|
||||||
|
|
|
@ -127,9 +127,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
// By default elements code falls back to a simple right action code.
|
// By default elements code falls back to a simple right action code.
|
||||||
virtual int elementsCount() const {
|
virtual int elementsCount() const;
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
virtual QRect elementGeometry(int element, int outerWidth) const;
|
virtual QRect elementGeometry(int element, int outerWidth) const;
|
||||||
virtual bool elementDisabled(int element) const;
|
virtual bool elementDisabled(int element) const;
|
||||||
virtual void elementAddRipple(
|
virtual void elementAddRipple(
|
||||||
|
|
|
@ -7,6 +7,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
*/
|
*/
|
||||||
#include "boxes/peers/edit_peer_requests_box.h"
|
#include "boxes/peers/edit_peer_requests_box.h"
|
||||||
|
|
||||||
|
#include "ui/effects/ripple_animation.h"
|
||||||
#include "boxes/peer_list_controllers.h"
|
#include "boxes/peer_list_controllers.h"
|
||||||
#include "boxes/peers/edit_participants_box.h" // SubscribeToMigration
|
#include "boxes/peers/edit_participants_box.h" // SubscribeToMigration
|
||||||
#include "data/data_peer.h"
|
#include "data/data_peer.h"
|
||||||
|
@ -14,55 +15,257 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "data/data_chat.h"
|
#include "data/data_chat.h"
|
||||||
#include "data/data_channel.h"
|
#include "data/data_channel.h"
|
||||||
#include "data/data_session.h"
|
#include "data/data_session.h"
|
||||||
|
#include "base/unixtime.h"
|
||||||
#include "main/main_session.h"
|
#include "main/main_session.h"
|
||||||
#include "mtproto/sender.h"
|
#include "mtproto/sender.h"
|
||||||
#include "lang/lang_keys.h"
|
#include "lang/lang_keys.h"
|
||||||
#include "window/window_session_controller.h"
|
#include "window/window_session_controller.h"
|
||||||
|
#include "styles/style_boxes.h"
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
constexpr auto kFirstPageCount = 16;
|
constexpr auto kFirstPageCount = 16;
|
||||||
constexpr auto kPerPage = 200;
|
constexpr auto kPerPage = 200;
|
||||||
constexpr auto kServerSearchDelay = crl::time(1000);
|
constexpr auto kServerSearchDelay = crl::time(1000);
|
||||||
|
constexpr auto kAcceptButton = 1;
|
||||||
|
constexpr auto kRejectButton = 2;
|
||||||
|
|
||||||
|
class RowDelegate {
|
||||||
|
public:
|
||||||
|
[[nodiscard]] virtual QSize rowAcceptButtonSize() = 0;
|
||||||
|
[[nodiscard]] virtual QSize rowRejectButtonSize() = 0;
|
||||||
|
virtual void rowPaintAccept(
|
||||||
|
Painter &p,
|
||||||
|
QRect geometry,
|
||||||
|
std::unique_ptr<Ui::RippleAnimation> &ripple,
|
||||||
|
int outerWidth,
|
||||||
|
bool over) = 0;
|
||||||
|
virtual void rowPaintReject(
|
||||||
|
Painter &p,
|
||||||
|
QRect geometry,
|
||||||
|
std::unique_ptr<Ui::RippleAnimation> &ripple,
|
||||||
|
int outerWidth,
|
||||||
|
bool over) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
class Row final : public PeerListRow {
|
class Row final : public PeerListRow {
|
||||||
public:
|
public:
|
||||||
Row(not_null<UserData*> user, TimeId date);
|
Row(
|
||||||
|
not_null<RowDelegate*> delegate,
|
||||||
|
not_null<UserData*> user,
|
||||||
|
TimeId date);
|
||||||
|
|
||||||
//QSize actionSize() const override;
|
int elementsCount() const override;
|
||||||
//void paintAction(
|
QRect elementGeometry(int element, int outerWidth) const override;
|
||||||
// Painter &p,
|
bool elementDisabled(int element) const override;
|
||||||
// int x,
|
void elementAddRipple(
|
||||||
// int y,
|
int element,
|
||||||
// int outerWidth,
|
QPoint point,
|
||||||
// bool selected,
|
Fn<void()> updateCallback) override;
|
||||||
// bool actionSelected) override;
|
void elementsStopLastRipple() override;
|
||||||
|
void elementsPaint(
|
||||||
//not_null<UserData*> user() const;
|
Painter &p,
|
||||||
|
int outerWidth,
|
||||||
|
bool selected,
|
||||||
|
int selectedElement) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
TimeId _date = 0;
|
const not_null<RowDelegate*> _delegate;
|
||||||
|
std::unique_ptr<Ui::RippleAnimation> _acceptRipple;
|
||||||
|
std::unique_ptr<Ui::RippleAnimation> _rejectRipple;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
Row::Row(not_null<UserData*> user, TimeId date)
|
Row::Row(
|
||||||
|
not_null<RowDelegate*> delegate,
|
||||||
|
not_null<UserData*> user,
|
||||||
|
TimeId date)
|
||||||
: PeerListRow(user)
|
: PeerListRow(user)
|
||||||
, _date(date) {
|
, _delegate(delegate) {
|
||||||
setCustomStatus(QString::number(_date));
|
const auto now = QDateTime::currentDateTime();
|
||||||
|
const auto parsed = base::unixtime::parse(date);
|
||||||
|
const auto parsedDate = parsed.date();
|
||||||
|
const auto time = parsed.time().toString(cTimeFormat());
|
||||||
|
const auto dateGeneric = [&] {
|
||||||
|
return tr::lng_group_call_starts_date(
|
||||||
|
tr::now,
|
||||||
|
lt_date,
|
||||||
|
langDayOfMonthFull(parsedDate),
|
||||||
|
lt_time,
|
||||||
|
time);
|
||||||
|
};
|
||||||
|
const auto dateString = (now.date().addDays(1) < parsedDate)
|
||||||
|
? dateGeneric()
|
||||||
|
: (now.date().addDays(1) == parsedDate)
|
||||||
|
? tr::lng_group_call_starts_tomorrow(tr::now, lt_time, time)
|
||||||
|
: (now.date() == parsedDate)
|
||||||
|
? time
|
||||||
|
: dateGeneric();
|
||||||
|
setCustomStatus(
|
||||||
|
tr::lng_group_requests_status(tr::now, lt_date, dateString));
|
||||||
|
}
|
||||||
|
|
||||||
|
int Row::elementsCount() const {
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
QRect Row::elementGeometry(int element, int outerWidth) const {
|
||||||
|
switch (element) {
|
||||||
|
case kAcceptButton: {
|
||||||
|
const auto size = _delegate->rowAcceptButtonSize();
|
||||||
|
return QRect(st::requestAcceptPosition, size);
|
||||||
|
} break;
|
||||||
|
case kRejectButton: {
|
||||||
|
const auto accept = _delegate->rowAcceptButtonSize();
|
||||||
|
const auto size = _delegate->rowRejectButtonSize();
|
||||||
|
return QRect(
|
||||||
|
(st::requestAcceptPosition
|
||||||
|
+ QPoint(accept.width() + st::requestButtonsSkip, 0)),
|
||||||
|
size);
|
||||||
|
} break;
|
||||||
|
}
|
||||||
|
return QRect();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Row::elementDisabled(int element) const {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Row::elementAddRipple(
|
||||||
|
int element,
|
||||||
|
QPoint point,
|
||||||
|
Fn<void()> updateCallback) {
|
||||||
|
const auto pointer = (element == kAcceptButton)
|
||||||
|
? &_acceptRipple
|
||||||
|
: (element == kRejectButton)
|
||||||
|
? &_rejectRipple
|
||||||
|
: nullptr;
|
||||||
|
if (!pointer) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
auto &ripple = *pointer;
|
||||||
|
if (!ripple) {
|
||||||
|
auto mask = Ui::RippleAnimation::roundRectMask(
|
||||||
|
(element == kAcceptButton
|
||||||
|
? _delegate->rowAcceptButtonSize()
|
||||||
|
: _delegate->rowRejectButtonSize()),
|
||||||
|
st::buttonRadius);
|
||||||
|
ripple = std::make_unique<Ui::RippleAnimation>(
|
||||||
|
(element == kAcceptButton
|
||||||
|
? st::requestsAcceptButton.ripple
|
||||||
|
: st::requestsRejectButton.ripple),
|
||||||
|
std::move(mask),
|
||||||
|
std::move(updateCallback));
|
||||||
|
}
|
||||||
|
ripple->add(point);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Row::elementsStopLastRipple() {
|
||||||
|
if (_acceptRipple) {
|
||||||
|
_acceptRipple->lastStop();
|
||||||
|
}
|
||||||
|
if (_rejectRipple) {
|
||||||
|
_rejectRipple->lastStop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Row::elementsPaint(
|
||||||
|
Painter &p,
|
||||||
|
int outerWidth,
|
||||||
|
bool selected,
|
||||||
|
int selectedElement) {
|
||||||
|
const auto accept = elementGeometry(kAcceptButton, outerWidth);
|
||||||
|
const auto reject = elementGeometry(kRejectButton, outerWidth);
|
||||||
|
|
||||||
|
const auto over = [&](int element) {
|
||||||
|
return (selectedElement == element);
|
||||||
|
};
|
||||||
|
_delegate->rowPaintAccept(
|
||||||
|
p,
|
||||||
|
accept,
|
||||||
|
_acceptRipple,
|
||||||
|
outerWidth,
|
||||||
|
over(kAcceptButton));
|
||||||
|
_delegate->rowPaintReject(
|
||||||
|
p,
|
||||||
|
reject,
|
||||||
|
_rejectRipple,
|
||||||
|
outerWidth,
|
||||||
|
over(kRejectButton));
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
|
class RequestsBoxController::RowHelper final : public RowDelegate {
|
||||||
|
public:
|
||||||
|
explicit RowHelper(bool isGroup);
|
||||||
|
|
||||||
|
[[nodiscard]] QSize rowAcceptButtonSize() override;
|
||||||
|
[[nodiscard]] QSize rowRejectButtonSize() override;
|
||||||
|
void rowPaintAccept(
|
||||||
|
Painter &p,
|
||||||
|
QRect geometry,
|
||||||
|
std::unique_ptr<Ui::RippleAnimation> &ripple,
|
||||||
|
int outerWidth,
|
||||||
|
bool over) override;
|
||||||
|
void rowPaintReject(
|
||||||
|
Painter &p,
|
||||||
|
QRect geometry,
|
||||||
|
std::unique_ptr<Ui::RippleAnimation> &ripple,
|
||||||
|
int outerWidth,
|
||||||
|
bool over) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void paintButton(
|
||||||
|
Painter &p,
|
||||||
|
QRect geometry,
|
||||||
|
const style::RoundButton &st,
|
||||||
|
const Ui::RoundRect &rect,
|
||||||
|
const Ui::RoundRect &rectOver,
|
||||||
|
std::unique_ptr<Ui::RippleAnimation> &ripple,
|
||||||
|
const QString &text,
|
||||||
|
int textWidth,
|
||||||
|
int outerWidth,
|
||||||
|
bool over);
|
||||||
|
|
||||||
|
Ui::RoundRect _acceptRect;
|
||||||
|
Ui::RoundRect _acceptRectOver;
|
||||||
|
Ui::RoundRect _rejectRect;
|
||||||
|
Ui::RoundRect _rejectRectOver;
|
||||||
|
QString _acceptText;
|
||||||
|
QString _rejectText;
|
||||||
|
int _acceptTextWidth = 0;
|
||||||
|
int _rejectTextWidth = 0;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
RequestsBoxController::RowHelper::RowHelper(bool isGroup)
|
||||||
|
: _acceptRect(st::buttonRadius, st::requestsAcceptButton.textBg)
|
||||||
|
, _acceptRectOver(st::buttonRadius, st::requestsAcceptButton.textBgOver)
|
||||||
|
, _rejectRect(st::buttonRadius, st::requestsRejectButton.textBg)
|
||||||
|
, _rejectRectOver(st::buttonRadius, st::requestsRejectButton.textBgOver)
|
||||||
|
, _acceptText(isGroup
|
||||||
|
? tr::lng_group_requests_add(tr::now)
|
||||||
|
: tr::lng_group_requests_add_channel(tr::now))
|
||||||
|
, _rejectText(tr::lng_group_requests_dismiss(tr::now))
|
||||||
|
, _acceptTextWidth(st::requestsAcceptButton.font->width(_acceptText))
|
||||||
|
, _rejectTextWidth(st::requestsRejectButton.font->width(_rejectText)) {
|
||||||
|
}
|
||||||
|
|
||||||
RequestsBoxController::RequestsBoxController(
|
RequestsBoxController::RequestsBoxController(
|
||||||
not_null<Window::SessionNavigation*> navigation,
|
not_null<Window::SessionNavigation*> navigation,
|
||||||
not_null<PeerData*> peer)
|
not_null<PeerData*> peer)
|
||||||
: PeerListController(CreateSearchController(peer))
|
: PeerListController(CreateSearchController(peer))
|
||||||
, _navigation(navigation)
|
, _navigation(navigation)
|
||||||
|
, _helper(std::make_unique<RowHelper>(!peer->isBroadcast()))
|
||||||
, _peer(peer)
|
, _peer(peer)
|
||||||
, _api(&_peer->session().mtp()) {
|
, _api(&_peer->session().mtp()) {
|
||||||
|
setStyleOverrides(&st::requestsBoxList);
|
||||||
subscribeToMigration();
|
subscribeToMigration();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RequestsBoxController::~RequestsBoxController() = default;
|
||||||
|
|
||||||
Main::Session &RequestsBoxController::session() const {
|
Main::Session &RequestsBoxController::session() const {
|
||||||
return _peer->session();
|
return _peer->session();
|
||||||
}
|
}
|
||||||
|
@ -150,6 +353,18 @@ void RequestsBoxController::rowClicked(not_null<PeerListRow*> row) {
|
||||||
_navigation->showPeerInfo(row->peer());
|
_navigation->showPeerInfo(row->peer());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RequestsBoxController::rowElementClicked(
|
||||||
|
not_null<PeerListRow*> row,
|
||||||
|
int element) {
|
||||||
|
processRequest(row->peer()->asUser(), (element == kAcceptButton));
|
||||||
|
}
|
||||||
|
|
||||||
|
void RequestsBoxController::processRequest(
|
||||||
|
not_null<UserData*> user,
|
||||||
|
bool approved) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
void RequestsBoxController::appendRow(
|
void RequestsBoxController::appendRow(
|
||||||
not_null<UserData*> user,
|
not_null<UserData*> user,
|
||||||
TimeId date) {
|
TimeId date) {
|
||||||
|
@ -161,6 +376,90 @@ void RequestsBoxController::appendRow(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QSize RequestsBoxController::RowHelper::rowAcceptButtonSize() {
|
||||||
|
const auto &st = st::requestsAcceptButton;
|
||||||
|
return {
|
||||||
|
(st.width <= 0) ? (_acceptTextWidth - st.width) : st.width,
|
||||||
|
st.height,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
QSize RequestsBoxController::RowHelper::rowRejectButtonSize() {
|
||||||
|
const auto &st = st::requestsRejectButton;
|
||||||
|
return {
|
||||||
|
(st.width <= 0) ? (_rejectTextWidth - st.width) : st.width,
|
||||||
|
st.height,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
void RequestsBoxController::RowHelper::rowPaintAccept(
|
||||||
|
Painter &p,
|
||||||
|
QRect geometry,
|
||||||
|
std::unique_ptr<Ui::RippleAnimation> &ripple,
|
||||||
|
int outerWidth,
|
||||||
|
bool over) {
|
||||||
|
paintButton(
|
||||||
|
p,
|
||||||
|
geometry,
|
||||||
|
st::requestsAcceptButton,
|
||||||
|
_acceptRect,
|
||||||
|
_acceptRectOver,
|
||||||
|
ripple,
|
||||||
|
_acceptText,
|
||||||
|
_acceptTextWidth,
|
||||||
|
outerWidth,
|
||||||
|
over);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RequestsBoxController::RowHelper::rowPaintReject(
|
||||||
|
Painter &p,
|
||||||
|
QRect geometry,
|
||||||
|
std::unique_ptr<Ui::RippleAnimation> &ripple,
|
||||||
|
int outerWidth,
|
||||||
|
bool over) {
|
||||||
|
paintButton(
|
||||||
|
p,
|
||||||
|
geometry,
|
||||||
|
st::requestsRejectButton,
|
||||||
|
_rejectRect,
|
||||||
|
_rejectRectOver,
|
||||||
|
ripple,
|
||||||
|
_rejectText,
|
||||||
|
_rejectTextWidth,
|
||||||
|
outerWidth,
|
||||||
|
over);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RequestsBoxController::RowHelper::paintButton(
|
||||||
|
Painter &p,
|
||||||
|
QRect geometry,
|
||||||
|
const style::RoundButton &st,
|
||||||
|
const Ui::RoundRect &rect,
|
||||||
|
const Ui::RoundRect &rectOver,
|
||||||
|
std::unique_ptr<Ui::RippleAnimation> &ripple,
|
||||||
|
const QString &text,
|
||||||
|
int textWidth,
|
||||||
|
int outerWidth,
|
||||||
|
bool over) {
|
||||||
|
rect.paint(p, geometry);
|
||||||
|
if (over) {
|
||||||
|
rectOver.paint(p, geometry);
|
||||||
|
}
|
||||||
|
if (ripple) {
|
||||||
|
ripple->paint(p, geometry.x(), geometry.y(), outerWidth);
|
||||||
|
if (ripple->empty()) {
|
||||||
|
ripple = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto textLeft = geometry.x()
|
||||||
|
+ ((geometry.width() - textWidth) / 2);
|
||||||
|
const auto textTop = geometry.y() + st.textTop;
|
||||||
|
p.setFont(st.font);
|
||||||
|
p.setPen(over ? st.textFgOver : st.textFg);
|
||||||
|
p.drawTextLeft(textLeft, textTop, outerWidth, text);
|
||||||
|
}
|
||||||
|
|
||||||
std::unique_ptr<PeerListRow> RequestsBoxController::createRow(
|
std::unique_ptr<PeerListRow> RequestsBoxController::createRow(
|
||||||
not_null<UserData*> user,
|
not_null<UserData*> user,
|
||||||
TimeId date) {
|
TimeId date) {
|
||||||
|
@ -169,7 +468,7 @@ std::unique_ptr<PeerListRow> RequestsBoxController::createRow(
|
||||||
searchController());
|
searchController());
|
||||||
date = search->dateForUser(user);
|
date = search->dateForUser(user);
|
||||||
}
|
}
|
||||||
return std::make_unique<Row>(user, date);
|
return std::make_unique<Row>(_helper.get(), user, date);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RequestsBoxController::subscribeToMigration() {
|
void RequestsBoxController::subscribeToMigration() {
|
||||||
|
|
|
@ -13,15 +13,21 @@ namespace Window {
|
||||||
class SessionNavigation;
|
class SessionNavigation;
|
||||||
} // namespace Window
|
} // namespace Window
|
||||||
|
|
||||||
|
namespace Ui {
|
||||||
|
class RippleAnimation;
|
||||||
|
} // namespace Ui
|
||||||
|
|
||||||
class RequestsBoxController final : public PeerListController {
|
class RequestsBoxController final : public PeerListController {
|
||||||
public:
|
public:
|
||||||
RequestsBoxController(
|
RequestsBoxController(
|
||||||
not_null<Window::SessionNavigation*> navigation,
|
not_null<Window::SessionNavigation*> navigation,
|
||||||
not_null<PeerData*> peer);
|
not_null<PeerData*> peer);
|
||||||
|
~RequestsBoxController();
|
||||||
|
|
||||||
Main::Session &session() const override;
|
Main::Session &session() const override;
|
||||||
void prepare() override;
|
void prepare() override;
|
||||||
void rowClicked(not_null<PeerListRow*> row) override;
|
void rowClicked(not_null<PeerListRow*> row) override;
|
||||||
|
void rowElementClicked(not_null<PeerListRow*> row, int element) override;
|
||||||
void loadMoreRows() override;
|
void loadMoreRows() override;
|
||||||
|
|
||||||
std::unique_ptr<PeerListRow> createSearchRow(
|
std::unique_ptr<PeerListRow> createSearchRow(
|
||||||
|
@ -33,6 +39,8 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
class RowHelper;
|
||||||
|
|
||||||
static std::unique_ptr<PeerListSearchController> CreateSearchController(
|
static std::unique_ptr<PeerListSearchController> CreateSearchController(
|
||||||
not_null<PeerData*> peer);
|
not_null<PeerData*> peer);
|
||||||
|
|
||||||
|
@ -48,6 +56,7 @@ private:
|
||||||
void migrate(not_null<ChatData*> chat, not_null<ChannelData*> channel);
|
void migrate(not_null<ChatData*> chat, not_null<ChannelData*> channel);
|
||||||
|
|
||||||
const not_null<Window::SessionNavigation*> _navigation;
|
const not_null<Window::SessionNavigation*> _navigation;
|
||||||
|
const std::unique_ptr<RowHelper> _helper;
|
||||||
not_null<PeerData*> _peer;
|
not_null<PeerData*> _peer;
|
||||||
MTP::Sender _api;
|
MTP::Sender _api;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue