Added initial ability to trigger quick dialog action with middle click.

This commit is contained in:
23rd 2025-03-18 12:57:05 +03:00
parent c332b7cb40
commit c11a7589e2
5 changed files with 141 additions and 38 deletions

View file

@ -1956,16 +1956,40 @@ bool InnerWidget::addQuickActionRipple(
.sizeOverride = Size(st::dialogsQuickActionSize), .sizeOverride = Size(st::dialogsQuickActionSize),
}); });
context->action = action; context->action = action;
const auto size = QSize( context->icon->jumpTo(context->icon->framesCount() - 1, [=] {
st::dialogsQuickActionRippleSize, const auto size = QSize(
row->height()); st::dialogsQuickActionRippleSize,
if (!context->ripple) { row->height());
context->ripple = std::make_unique<Ui::RippleAnimation>( if (!context->ripple) {
st::defaultRippleAnimation, context->ripple = std::make_unique<Ui::RippleAnimation>(
Ui::RippleAnimation::RectMask(size), st::defaultRippleAnimation,
std::move(updateCallback)); Ui::RippleAnimation::RectMask(size),
} updateCallback);
context->ripple->add(QPoint(size.width() / 2, size.height() / 2)); }
if (!context->rippleFg) {
context->rippleFg = std::make_unique<Ui::RippleAnimation>(
st::defaultRippleAnimation,
Ui::RippleAnimation::MaskByDrawer(
size,
true,
[&](QPainter &p) {
p.setCompositionMode(
QPainter::CompositionMode_Source);
p.fillRect(Rect(size), Qt::transparent);
DrawQuickAction(
p,
Rect(size),
context->icon.get(),
ResolveQuickDialogLabel(
row->history(),
action,
_filterId));
}),
std::move(updateCallback));
}
context->ripple->add(QPoint(size.width() / 2, size.height() / 2));
context->rippleFg->add(QPoint(size.width() / 2, size.height() / 2));
});
return true; return true;
} }
@ -2281,7 +2305,13 @@ void InnerWidget::mousePressReleased(
if (it != _quickActions.end()) { if (it != _quickActions.end()) {
if (it->second->ripple) { if (it->second->ripple) {
it->second->ripple->lastStop(); it->second->ripple->lastStop();
it->second->rippleFg->lastStop();
} }
PerformQuickDialogAction(
_controller,
history->peer,
it->second->action,
_filterId);
} }
} }
} }

View file

@ -14,13 +14,55 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "data/data_session.h" #include "data/data_session.h"
#include "dialogs/dialogs_entry.h" #include "dialogs/dialogs_entry.h"
#include "history/history.h" #include "history/history.h"
#include "lang/lang_instance.h"
#include "lang/lang_keys.h" #include "lang/lang_keys.h"
#include "lottie/lottie_icon.h"
#include "main/main_session.h" #include "main/main_session.h"
#include "menu/menu_mute.h" #include "menu/menu_mute.h"
#include "window/window_peer_menu.h" #include "window/window_peer_menu.h"
#include "window/window_session_controller.h" #include "window/window_session_controller.h"
#include "styles/style_dialogs.h"
namespace Dialogs { namespace Dialogs {
namespace {
const style::font &SwipeActionFont(
Dialogs::Ui::QuickDialogActionLabel action,
int availableWidth) {
struct Entry final {
Dialogs::Ui::QuickDialogActionLabel action;
QString langId;
style::font font;
};
static auto Fonts = std::vector<Entry>();
for (auto &entry : Fonts) {
if (entry.action == action) {
if (entry.langId == Lang::GetInstance().id()) {
return entry.font;
}
}
}
constexpr auto kNormalFontSize = 13;
constexpr auto kMinFontSize = 5;
for (auto i = kNormalFontSize; i >= kMinFontSize; --i) {
auto font = style::font(
style::ConvertScale(i, style::Scale()),
st::semiboldFont->flags(),
st::semiboldFont->family());
if (font->width(ResolveQuickDialogLabel(action)) <= availableWidth
|| i == kMinFontSize) {
Fonts.emplace_back(Entry{
.action = action,
.langId = Lang::GetInstance().id(),
.font = std::move(font),
});
return Fonts.back().font;
}
}
Unexpected("SwipeActionFont: can't find font.");
}
} // namespace
void PerformQuickDialogAction( void PerformQuickDialogAction(
not_null<Window::SessionController*> controller, not_null<Window::SessionController*> controller,
@ -163,4 +205,23 @@ const style::color &ResolveQuickActionBgActive(
return st::windowSubTextFgOver; return st::windowSubTextFgOver;
} }
void DrawQuickAction(
QPainter &p,
const QRect &rect,
not_null<Lottie::Icon*> icon,
Ui::QuickDialogActionLabel label) {
const auto iconSize = st::dialogsQuickActionSize;
const auto innerHeight = iconSize * 2;
const auto top = (rect.height() - innerHeight) / 2;
icon->paint(p, rect.x() + (rect.width() - iconSize) / 2, top);
p.setPen(st::premiumButtonFg);
p.setBrush(Qt::NoBrush);
const auto availableWidth = rect.width();
p.setFont(SwipeActionFont(label, availableWidth));
p.drawText(
QRect(rect.x(), top, availableWidth, innerHeight),
ResolveQuickDialogLabel(label),
style::al_bottom);
}
} // namespace Dialogs } // namespace Dialogs

View file

@ -15,6 +15,10 @@ enum class QuickDialogAction;
enum class QuickDialogActionLabel; enum class QuickDialogActionLabel;
} // namespace Dialogs::Ui } // namespace Dialogs::Ui
namespace Lottie {
class Icon;
} // namespace Lottie
namespace Window { namespace Window {
class SessionController; class SessionController;
} // namespace Window } // namespace Window
@ -44,4 +48,10 @@ void PerformQuickDialogAction(
[[nodiscard]] const style::color &ResolveQuickActionBgActive( [[nodiscard]] const style::color &ResolveQuickActionBgActive(
Ui::QuickDialogActionLabel); Ui::QuickDialogActionLabel);
void DrawQuickAction(
QPainter &p,
const QRect &rect,
not_null<Lottie::Icon*> icon,
Ui::QuickDialogActionLabel label);
} // namespace Dialogs } // namespace Dialogs

View file

@ -878,7 +878,7 @@ void PaintRow(
if (swipeTranslation) { if (swipeTranslation) {
p.translate(swipeTranslation, 0); p.translate(swipeTranslation, 0);
const auto swipeActionRect = QRect( const auto swipeActionRect = QRect(
geometry.x() + geometry.width() - swipeTranslation, rect::right(geometry) - swipeTranslation,
geometry.y(), geometry.y(),
swipeTranslation, swipeTranslation,
geometry.height()); geometry.height());
@ -897,35 +897,36 @@ void PaintRow(
+ st::dialogsQuickActionSize / 2.; + st::dialogsQuickActionSize / 2.;
p.drawEllipse(QPointF(geometry.width() - offset, offset), r, r); p.drawEllipse(QPointF(geometry.width() - offset, offset), r, r);
} }
const auto iconOffset = (geometry.height() const auto quickWidth = st::dialogsQuickActionSize * 3;
- st::dialogsQuickActionSize) / 2; DrawQuickAction(
const auto topTranslation = iconOffset / 2.; p,
p.translate(0, -topTranslation); QRect(
if (context.quickActionContext->icon) { rect::right(geometry) - quickWidth,
context.quickActionContext->icon->paint( geometry.y(),
p, quickWidth,
rect::right(geometry) geometry.height()),
- iconOffset context.quickActionContext->icon.get(),
- st::dialogsQuickActionSize, labelType);
iconOffset,
st::premiumButtonFg->c);
}
{
p.setPen(st::premiumButtonFg);
p.setBrush(Qt::NoBrush);
const auto left = rect::right(geometry)
- iconOffset * 2
- st::dialogsQuickActionSize;
const auto availableWidth = geometry.width() - left;
p.setFont(SwipeActionFont(labelType, availableWidth));
p.drawText(
QRect(left, 0, availableWidth, geometry.height()),
ResolveQuickDialogLabel(labelType),
style::al_bottom);
}
p.translate(0, topTranslation);
p.setClipping(false); p.setClipping(false);
} }
if (const auto quick = context.quickActionContext;
quick && quick->ripple && quick->rippleFg) {
const auto labelType = ResolveQuickDialogLabel(
history,
context.quickActionContext->action,
context.filter);
const auto ripple = ResolveQuickActionBg(labelType);
const auto size = st::dialogsQuickActionRippleSize;
const auto x = geometry.width() - size;
quick->ripple->paint(p, x, 0, size, &ripple->c);
quick->rippleFg->paint(p, x, 0, size, &st::premiumButtonFg->c);
if (quick->ripple->empty()) {
quick->ripple.reset();
}
if (quick->rippleFg->empty()) {
quick->rippleFg.reset();
}
}
} }
} // namespace } // namespace

View file

@ -39,6 +39,7 @@ struct QuickActionContext {
::Ui::Controls::SwipeContextData data; ::Ui::Controls::SwipeContextData data;
std::unique_ptr<Lottie::Icon> icon; std::unique_ptr<Lottie::Icon> icon;
std::unique_ptr<Ui::RippleAnimation> ripple; std::unique_ptr<Ui::RippleAnimation> ripple;
std::unique_ptr<Ui::RippleAnimation> rippleFg;
QuickDialogAction action; QuickDialogAction action;
}; };