Added right button for bots in list from recent dialogs.

This commit is contained in:
23rd 2024-11-25 12:25:36 +03:00
parent 6c62bbe6fb
commit a9824fde91
5 changed files with 114 additions and 14 deletions

View file

@ -112,6 +112,7 @@ dialogRowOpenBotTextStyle: semiboldTextStyle;
dialogRowOpenBotHeight: 20px; dialogRowOpenBotHeight: 20px;
dialogRowOpenBotRight: 10px; dialogRowOpenBotRight: 10px;
dialogRowOpenBotTop: 32px; dialogRowOpenBotTop: 32px;
dialogRowOpenBotRecentTop: 28px;
forumDialogJumpArrow: icon{{ "dialogs/dialogs_topic_arrow", dialogsTextFg }}; forumDialogJumpArrow: icon{{ "dialogs/dialogs_topic_arrow", dialogsTextFg }};
forumDialogJumpArrowOver: icon{{ "dialogs/dialogs_topic_arrow", dialogsTextFgOver }}; forumDialogJumpArrowOver: icon{{ "dialogs/dialogs_topic_arrow", dialogsTextFgOver }};

View file

@ -1443,7 +1443,9 @@ void Widget::updateSuggestions(anim::type animated) {
} }
}, _suggestions->lifetime()); }, _suggestions->lifetime());
_suggestions->recentAppChosen( rpl::merge(
_suggestions->openBotMainAppRequests(),
_suggestions->recentAppChosen()
) | rpl::start_with_next([=](not_null<PeerData*> peer) { ) | rpl::start_with_next([=](not_null<PeerData*> peer) {
if (const auto user = peer->asUser()) { if (const auto user = peer->asUser()) {
if (const auto info = user->botInfo.get()) { if (const auto info = user->botInfo.get()) {

View file

@ -28,6 +28,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "main/main_session.h" #include "main/main_session.h"
#include "settings/settings_common.h" #include "settings/settings_common.h"
#include "ui/boxes/confirm_box.h" #include "ui/boxes/confirm_box.h"
#include "ui/effects/ripple_animation.h"
#include "ui/text/text_utilities.h" #include "ui/text/text_utilities.h"
#include "ui/widgets/menu/menu_add_action_callback_factory.h" #include "ui/widgets/menu/menu_add_action_callback_factory.h"
#include "ui/widgets/buttons.h" #include "ui/widgets/buttons.h"
@ -76,12 +77,18 @@ public:
bool selected, bool selected,
bool actionSelected) override; bool actionSelected) override;
bool rightActionDisabled() const override; bool rightActionDisabled() const override;
void rightActionAddRipple(
QPoint point,
Fn<void()> updateCallback) override;
void rightActionStopLastRipple() override;
const style::PeerListItem &computeSt( const style::PeerListItem &computeSt(
const style::PeerListItem &st) const override; const style::PeerListItem &st) const override;
private: private:
const not_null<History*> _history; const not_null<History*> _history;
std::unique_ptr<Ui::Text::String> _mainAppText;
std::unique_ptr<Ui::RippleAnimation> _actionRipple;
QString _badgeString; QString _badgeString;
QSize _badgeSize; QSize _badgeSize;
uint32 _counter : 30 = 0; uint32 _counter : 30 = 0;
@ -181,7 +188,17 @@ void FillEntryMenu(
RecentRow::RecentRow(not_null<PeerData*> peer) RecentRow::RecentRow(not_null<PeerData*> peer)
: PeerListRow(peer) : PeerListRow(peer)
, _history(peer->owner().history(peer)) { , _history(peer->owner().history(peer))
, _mainAppText([&]() -> std::unique_ptr<Ui::Text::String> {
if (const auto user = peer->asUser()) {
if (user->botInfo && user->botInfo->hasMainApp) {
return std::make_unique<Ui::Text::String>(
st::dialogRowOpenBotTextStyle,
tr::lng_profile_open_app_short(tr::now).toUpper());
}
}
return nullptr;
}()) {
if (peer->isSelf() || peer->isRepliesChat() || peer->isVerifyCodes()) { if (peer->isSelf() || peer->isRepliesChat() || peer->isVerifyCodes()) {
setCustomStatus(u" "_q); setCustomStatus(u" "_q);
} else if (const auto chat = peer->asChat()) { } else if (const auto chat = peer->asChat()) {
@ -244,10 +261,23 @@ bool RecentRow::refreshBadge() {
} }
QSize RecentRow::rightActionSize() const { QSize RecentRow::rightActionSize() const {
if (_mainAppText) {
const auto &font = st::dialogRowOpenBotTextStyle.font;
return QSize(
_mainAppText->maxWidth() + _mainAppText->minHeight(),
st::dialogRowOpenBotHeight);
}
return _badgeSize; return _badgeSize;
} }
QMargins RecentRow::rightActionMargins() const { QMargins RecentRow::rightActionMargins() const {
if (_mainAppText) {
return QMargins(
0,
st::dialogRowOpenBotRecentTop,
st::dialogRowOpenBotRight,
0);
}
if (_badgeSize.isEmpty()) { if (_badgeSize.isEmpty()) {
return {}; return {};
} }
@ -263,6 +293,32 @@ void RecentRow::rightActionPaint(
int outerWidth, int outerWidth,
bool selected, bool selected,
bool actionSelected) { bool actionSelected) {
if (_mainAppText) {
const auto size = RecentRow::rightActionSize();
p.setPen(Qt::NoPen);
p.setBrush(actionSelected
? st::activeButtonBgOver
: st::activeButtonBg);
const auto radius = size.height() / 2;
p.drawRoundedRect(QRect(QPoint(x, y), size), radius, radius);
if (_actionRipple) {
_actionRipple->paint(p, x, y, outerWidth);
if (_actionRipple->empty()) {
_actionRipple.reset();
}
}
p.setPen(actionSelected
? st::activeButtonFgOver
: st::activeButtonFg);
const auto top = 0
+ (st::dialogRowOpenBotHeight - _mainAppText->minHeight()) / 2;
_mainAppText->draw(p, {
.position = QPoint(x + size.height() / 2, y + top),
.availableWidth = outerWidth,
.outerWidth = outerWidth,
.elisionLines = 1,
});
}
if (!_counter && !_unread) { if (!_counter && !_unread) {
return; return;
} else if (_badgeString.isEmpty()) { } else if (_badgeString.isEmpty()) {
@ -280,7 +336,31 @@ void RecentRow::rightActionPaint(
} }
bool RecentRow::rightActionDisabled() const { bool RecentRow::rightActionDisabled() const {
return true; return !_mainAppText;
}
void RecentRow::rightActionAddRipple(
QPoint point,
Fn<void()> updateCallback) {
if (!_mainAppText) {
return;
}
if (!_actionRipple) {
const auto size = rightActionSize();
const auto radius = size.height() / 2;
auto mask = Ui::RippleAnimation::RoundRectMask(size, radius);
_actionRipple = std::make_unique<Ui::RippleAnimation>(
st::defaultActiveButton.ripple,
std::move(mask),
std::move(updateCallback));
}
_actionRipple->add(point);
}
void RecentRow::rightActionStopLastRipple() {
if (_actionRipple) {
_actionRipple->lastStop();
}
} }
const style::PeerListItem &RecentRow::computeSt( const style::PeerListItem &RecentRow::computeSt(
@ -357,14 +437,18 @@ private:
class RecentsController final : public Suggestions::ObjectListController { class RecentsController final : public Suggestions::ObjectListController {
public: public:
using RightActionCallback = Fn<void(not_null<PeerData*>)>;
RecentsController( RecentsController(
not_null<Window::SessionController*> window, not_null<Window::SessionController*> window,
RecentPeersList list); RecentPeersList list,
RightActionCallback rightActionCallback);
void prepare() override; void prepare() override;
base::unique_qptr<Ui::PopupMenu> rowContextMenu( base::unique_qptr<Ui::PopupMenu> rowContextMenu(
QWidget *parent, QWidget *parent,
not_null<PeerListRow*> row) override; not_null<PeerListRow*> row) override;
void rowRightActionClicked(not_null<PeerListRow*> row) override;
QString savedMessagesChatStatus() const override; QString savedMessagesChatStatus() const override;
@ -374,6 +458,7 @@ private:
[[nodiscard]] Fn<void()> removeAllCallback(); [[nodiscard]] Fn<void()> removeAllCallback();
RecentPeersList _recent; RecentPeersList _recent;
RightActionCallback _rightActionCallback;
rpl::lifetime _lifetime; rpl::lifetime _lifetime;
}; };
@ -671,9 +756,11 @@ void Suggestions::ObjectListController::setupExpandDivider(
RecentsController::RecentsController( RecentsController::RecentsController(
not_null<Window::SessionController*> window, not_null<Window::SessionController*> window,
RecentPeersList list) RecentPeersList list,
RightActionCallback rightActionCallback)
: ObjectListController(window) : ObjectListController(window)
, _recent(std::move(list)) { , _recent(std::move(list))
, _rightActionCallback(std::move(rightActionCallback)) {
} }
void RecentsController::prepare() { void RecentsController::prepare() {
@ -735,6 +822,14 @@ base::unique_qptr<Ui::PopupMenu> RecentsController::rowContextMenu(
return result; return result;
} }
void RecentsController::rowRightActionClicked(not_null<PeerListRow*> row) {
if (_rightActionCallback) {
if (const auto peer = row->peer()) {
_rightActionCallback(peer);
}
}
}
QString RecentsController::savedMessagesChatStatus() const { QString RecentsController::savedMessagesChatStatus() const {
return tr::lng_saved_forward_here(tr::now); return tr::lng_saved_forward_here(tr::now);
} }
@ -1785,7 +1880,8 @@ auto Suggestions::setupRecentPeers(RecentPeersList recentPeers)
-> std::unique_ptr<ObjectList> { -> std::unique_ptr<ObjectList> {
const auto controller = lifetime().make_state<RecentsController>( const auto controller = lifetime().make_state<RecentsController>(
_controller, _controller,
std::move(recentPeers)); std::move(recentPeers),
[=](not_null<PeerData*> p) { _openBotMainAppRequests.fire_copy(p); });
const auto addToScroll = [=] { const auto addToScroll = [=] {
return _topPeersWrap->toggled() ? _topPeers->height() : 0; return _topPeersWrap->toggled() ? _topPeers->height() : 0;

View file

@ -88,6 +88,10 @@ public:
-> rpl::producer<not_null<PeerData*>> { -> rpl::producer<not_null<PeerData*>> {
return _popularApps->chosen.events(); return _popularApps->chosen.events();
} }
[[nodiscard]] auto openBotMainAppRequests() const
-> rpl::producer<not_null<PeerData*>> {
return _openBotMainAppRequests.events();
}
class ObjectListController; class ObjectListController;
@ -174,6 +178,7 @@ private:
const not_null<Ui::SlideWrap<TopPeersStrip>*> _topPeersWrap; const not_null<Ui::SlideWrap<TopPeersStrip>*> _topPeersWrap;
const not_null<TopPeersStrip*> _topPeers; const not_null<TopPeersStrip*> _topPeers;
rpl::event_stream<not_null<PeerData*>> _topPeerChosen; rpl::event_stream<not_null<PeerData*>> _topPeerChosen;
rpl::event_stream<not_null<PeerData*>> _openBotMainAppRequests;
const std::unique_ptr<ObjectList> _recent; const std::unique_ptr<ObjectList> _recent;

View file

@ -134,11 +134,7 @@ void PreviewRow::rightActionPaint(
bool selected, bool selected,
bool actionSelected) { bool actionSelected) {
if (_actionRipple) { if (_actionRipple) {
_actionRipple->paint( _actionRipple->paint(p, x, y, outerWidth);
p,
x,
y,
outerWidth);
if (_actionRipple->empty()) { if (_actionRipple->empty()) {
_actionRipple.reset(); _actionRipple.reset();
} }
@ -150,8 +146,8 @@ void PreviewRow::rightActionPaint(
} }
void PreviewRow::rightActionAddRipple( void PreviewRow::rightActionAddRipple(
QPoint point, QPoint point,
Fn<void()> updateCallback) { Fn<void()> updateCallback) {
if (!_actionRipple) { if (!_actionRipple) {
auto mask = Ui::RippleAnimation::EllipseMask(rightActionSize()); auto mask = Ui::RippleAnimation::EllipseMask(rightActionSize());
_actionRipple = std::make_unique<Ui::RippleAnimation>( _actionRipple = std::make_unique<Ui::RippleAnimation>(