Apply connected programs in realtime.

This commit is contained in:
John Preston 2024-11-29 17:11:47 +04:00
parent fd26e1618c
commit 747e417809
3 changed files with 68 additions and 41 deletions

View file

@ -302,7 +302,8 @@ object_ptr<Ui::BoxContent> StarRefLinkBox(
[[nodiscard]] object_ptr<Ui::BoxContent> JoinStarRefBox( [[nodiscard]] object_ptr<Ui::BoxContent> JoinStarRefBox(
ConnectedBot row, ConnectedBot row,
not_null<PeerData*> peer) { not_null<PeerData*> peer,
Fn<void(ConnectedBotState)> done) {
Expects(row.bot->isUser()); Expects(row.bot->isUser());
return Box([=](not_null<Ui::GenericBox*> box) { return Box([=](not_null<Ui::GenericBox*> box) {
@ -372,6 +373,7 @@ object_ptr<Ui::BoxContent> StarRefLinkBox(
} }
state->sent = true; state->sent = true;
ConnectStarRef(bot->asUser(), peer, [=](ConnectedBot info) { ConnectStarRef(bot->asUser(), peer, [=](ConnectedBot info) {
done(info.state);
show->show(StarRefLinkBox(info, peer)); show->show(StarRefLinkBox(info, peer));
if (const auto strong = state->weak.data()) { if (const auto strong = state->weak.data()) {
strong->closeBox(); strong->closeBox();

View file

@ -63,7 +63,8 @@ void AddFullWidthButtonFooter(
not_null<PeerData*> peer); not_null<PeerData*> peer);
[[nodiscard]] object_ptr<Ui::BoxContent> JoinStarRefBox( [[nodiscard]] object_ptr<Ui::BoxContent> JoinStarRefBox(
ConnectedBot row, ConnectedBot row,
not_null<PeerData*> peer); not_null<PeerData*> peer,
Fn<void(ConnectedBotState)> done);
std::unique_ptr<Ui::AbstractButton> MakePeerBubbleButton( std::unique_ptr<Ui::AbstractButton> MakePeerBubbleButton(
not_null<QWidget*> parent, not_null<QWidget*> parent,

View file

@ -75,9 +75,9 @@ public:
void loadMoreRows() override; void loadMoreRows() override;
[[nodiscard]] rpl::producer<int> rowCountValue() const; [[nodiscard]] rpl::producer<int> rowCountValue() const;
[[nodiscard]] rpl::producer<ConnectedBot> connected() const;
void setContentWidget(not_null<Ui::RpWidget*> widget); void process(ConnectedBot row);
[[nodiscard]] rpl::producer<int> unlockHeightValue() const;
private: private:
[[nodiscard]] std::unique_ptr<PeerListRow> createRow(ConnectedBot bot); [[nodiscard]] std::unique_ptr<PeerListRow> createRow(ConnectedBot bot);
@ -91,6 +91,8 @@ private:
base::flat_set<not_null<PeerData*>> _resolving; base::flat_set<not_null<PeerData*>> _resolving;
UserData *_openOnResolve = nullptr; UserData *_openOnResolve = nullptr;
rpl::event_stream<ConnectedBot> _connected;
mtpRequestId _requestId = 0; mtpRequestId _requestId = 0;
TimeId _offsetDate = 0; TimeId _offsetDate = 0;
QString _offsetThing; QString _offsetThing;
@ -127,6 +129,7 @@ ListController::ListController(
, _controller(controller) , _controller(controller)
, _peer(peer) , _peer(peer)
, _type(type) { , _type(type) {
setStyleOverrides(&st::peerListSingleRow);
} }
ListController::~ListController() { ListController::~ListController() {
@ -162,7 +165,6 @@ void ListController::prepare() {
delegate()->peerListSetTitle((_type == JoinType::Joined) delegate()->peerListSetTitle((_type == JoinType::Joined)
? tr::lng_star_ref_list_my() ? tr::lng_star_ref_list_my()
: tr::lng_star_ref_list_title()); : tr::lng_star_ref_list_title());
loadMoreRows(); loadMoreRows();
} }
@ -196,12 +198,13 @@ void ListController::loadMoreRows() {
}).send(); }).send();
} else { } else {
using Flag = MTPpayments_GetSuggestedStarRefBots::Flag; using Flag = MTPpayments_GetSuggestedStarRefBots::Flag;
_requestId = session().api().request(MTPpayments_GetSuggestedStarRefBots( _requestId = session().api().request(
MTP_flags(Flag::f_order_by_revenue), MTPpayments_GetSuggestedStarRefBots(
_peer->input, MTP_flags(Flag::f_order_by_revenue),
MTP_string(_offsetThing), _peer->input,
MTP_int(kPerPage) MTP_string(_offsetThing),
)).done([=](const MTPpayments_SuggestedStarRefBots &result) { MTP_int(kPerPage))
).done([=](const MTPpayments_SuggestedStarRefBots &result) {
const auto &data = result.data(); const auto &data = result.data();
if (data.vnext_offset()) { if (data.vnext_offset()) {
_offsetThing = qs(*data.vnext_offset()); _offsetThing = qs(*data.vnext_offset());
@ -241,6 +244,17 @@ rpl::producer<int> ListController::rowCountValue() const {
return _rowCount.value(); return _rowCount.value();
} }
rpl::producer<ConnectedBot> ListController::connected() const {
return _connected.events();
}
void ListController::process(ConnectedBot row) {
if (!delegate()->peerListFindRow(PeerListRowId(row.bot->id.value))) {
delegate()->peerListPrependRow(createRow(row));
delegate()->peerListRefreshRows();
}
}
void ListController::rowClicked(not_null<PeerListRow*> row) { void ListController::rowClicked(not_null<PeerListRow*> row) {
const auto bot = row->peer()->asUser(); const auto bot = row->peer()->asUser();
const auto i = _states.find(bot); const auto i = _states.find(bot);
@ -255,8 +269,6 @@ void ListController::rowClicked(not_null<PeerListRow*> row) {
auto &now = _states[bot]; auto &now = _states[bot];
if (state) { if (state) {
now = *state; now = *state;
} else {
now.unresolved = false;
} }
if (_openOnResolve == bot) { if (_openOnResolve == bot) {
open(bot, now); open(bot, now);
@ -273,7 +285,11 @@ void ListController::open(not_null<UserData*> bot, ConnectedBotState state) {
if (_type == JoinType::Joined || !state.link.isEmpty()) { if (_type == JoinType::Joined || !state.link.isEmpty()) {
_controller->show(StarRefLinkBox({ bot, state }, _peer)); _controller->show(StarRefLinkBox({ bot, state }, _peer));
} else { } else {
_controller->show(JoinStarRefBox({ bot, state }, _peer)); const auto connected = crl::guard(this, [=](ConnectedBotState now) {
_states[bot] = now;
_connected.fire({ bot, now });
});
_controller->show(JoinStarRefBox({ bot, state }, _peer, connected));
} }
} }
@ -284,9 +300,6 @@ base::unique_qptr<Ui::PopupMenu> ListController::rowContextMenu(
const auto i = _states.find(bot); const auto i = _states.find(bot);
Assert(i != end(_states)); Assert(i != end(_states));
const auto state = i->second; const auto state = i->second;
if (state.link.isEmpty()) {
return nullptr;
}
auto result = base::make_unique_q<Ui::PopupMenu>( auto result = base::make_unique_q<Ui::PopupMenu>(
parent, parent,
st::popupMenuWithIcons); st::popupMenuWithIcons);
@ -295,27 +308,29 @@ base::unique_qptr<Ui::PopupMenu> ListController::rowContextMenu(
addAction(tr::lng_star_ref_list_my_open(tr::now), [=] { addAction(tr::lng_star_ref_list_my_open(tr::now), [=] {
_controller->showPeerHistory(bot); _controller->showPeerHistory(bot);
}, &st::menuIconBot); }, &st::menuIconBot);
addAction(tr::lng_star_ref_list_my_copy(tr::now), [=] { if (!state.link.isEmpty()) {
QApplication::clipboard()->setText(state.link); addAction(tr::lng_star_ref_list_my_copy(tr::now), [=] {
_controller->showToast(tr::lng_username_copied(tr::now)); QApplication::clipboard()->setText(state.link);
}, &st::menuIconLinks); _controller->showToast(tr::lng_username_copied(tr::now));
const auto revoke = [=] { }, &st::menuIconLinks);
session().api().request(MTPpayments_EditConnectedStarRefBot( const auto revoke = [=] {
MTP_flags(MTPpayments_EditConnectedStarRefBot::Flag::f_revoked), session().api().request(MTPpayments_EditConnectedStarRefBot(
_peer->input, MTP_flags(MTPpayments_EditConnectedStarRefBot::Flag::f_revoked),
MTP_string(state.link) _peer->input,
)).done([=] { MTP_string(state.link)
_controller->showToast(u"Revoked!"_q); )).done([=] {
}).fail([=](const MTP::Error &error) { _controller->showToast(u"Revoked!"_q);
_controller->showToast(u"Failed: "_q + error.type()); }).fail([=](const MTP::Error &error) {
}).send(); _controller->showToast(u"Failed: "_q + error.type());
}; }).send();
addAction({ };
.text = tr::lng_star_ref_list_my_leave(tr::now), addAction({
.handler = revoke, .text = tr::lng_star_ref_list_my_leave(tr::now),
.icon = &st::menuIconLeaveAttention, .handler = revoke,
.isAttention = true, .icon = &st::menuIconLeaveAttention,
}); .isAttention = true,
});
}
return result; return result;
} }
@ -336,7 +351,7 @@ public:
private: private:
void prepare(); void prepare();
void setupInfo(); void setupInfo();
void setupMy(); not_null<ListController*> setupMy();
void setupSuggested(); void setupSuggested();
[[nodiscard]] object_ptr<Ui::RpWidget> infoRow( [[nodiscard]] object_ptr<Ui::RpWidget> infoRow(
@ -346,6 +361,7 @@ private:
const not_null<Controller*> _controller; const not_null<Controller*> _controller;
const not_null<Ui::VerticalLayout*> _container; const not_null<Ui::VerticalLayout*> _container;
ListController *_my = nullptr;
}; };
@ -362,7 +378,7 @@ void InnerWidget::prepare() {
setupInfo(); setupInfo();
Ui::AddSkip(_container); Ui::AddSkip(_container);
Ui::AddDivider(_container); Ui::AddDivider(_container);
setupMy(); _my = setupMy();
setupSuggested(); setupSuggested();
} }
@ -385,7 +401,7 @@ void InnerWidget::setupInfo() {
&st::menuIconLike)); &st::menuIconLike));
} }
void InnerWidget::setupMy() { not_null<ListController*> InnerWidget::setupMy() {
const auto wrap = _container->add( const auto wrap = _container->add(
object_ptr<Ui::SlideWrap<Ui::VerticalLayout>>( object_ptr<Ui::SlideWrap<Ui::VerticalLayout>>(
_container, _container,
@ -409,10 +425,13 @@ void InnerWidget::setupMy() {
delegate->setContent(content); delegate->setContent(content);
controller->setDelegate(delegate); controller->setDelegate(delegate);
Ui::AddSkip(inner);
Ui::AddDivider(inner); Ui::AddDivider(inner);
wrap->toggleOn(controller->rowCountValue( wrap->toggleOn(controller->rowCountValue(
) | rpl::map(rpl::mappers::_1 > 0)); ) | rpl::map(rpl::mappers::_1 > 0));
return controller;
} }
void InnerWidget::setupSuggested() { void InnerWidget::setupSuggested() {
@ -432,6 +451,11 @@ void InnerWidget::setupSuggested() {
controller)); controller));
delegate->setContent(content); delegate->setContent(content);
controller->setDelegate(delegate); controller->setDelegate(delegate);
controller->connected(
) | rpl::start_with_next([=](ConnectedBot row) {
_my->process(row);
}, content->lifetime());
} }
object_ptr<Ui::RpWidget> InnerWidget::infoRow( object_ptr<Ui::RpWidget> InnerWidget::infoRow(