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,6 +1956,7 @@ bool InnerWidget::addQuickActionRipple(
.sizeOverride = Size(st::dialogsQuickActionSize),
});
context->action = action;
context->icon->jumpTo(context->icon->framesCount() - 1, [=] {
const auto size = QSize(
st::dialogsQuickActionRippleSize,
row->height());
@ -1963,9 +1964,32 @@ bool InnerWidget::addQuickActionRipple(
context->ripple = std::make_unique<Ui::RippleAnimation>(
st::defaultRippleAnimation,
Ui::RippleAnimation::RectMask(size),
updateCallback);
}
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;
}
@ -2281,7 +2305,13 @@ void InnerWidget::mousePressReleased(
if (it != _quickActions.end()) {
if (it->second->ripple) {
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 "dialogs/dialogs_entry.h"
#include "history/history.h"
#include "lang/lang_instance.h"
#include "lang/lang_keys.h"
#include "lottie/lottie_icon.h"
#include "main/main_session.h"
#include "menu/menu_mute.h"
#include "window/window_peer_menu.h"
#include "window/window_session_controller.h"
#include "styles/style_dialogs.h"
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(
not_null<Window::SessionController*> controller,
@ -163,4 +205,23 @@ const style::color &ResolveQuickActionBgActive(
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

View file

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

View file

@ -878,7 +878,7 @@ void PaintRow(
if (swipeTranslation) {
p.translate(swipeTranslation, 0);
const auto swipeActionRect = QRect(
geometry.x() + geometry.width() - swipeTranslation,
rect::right(geometry) - swipeTranslation,
geometry.y(),
swipeTranslation,
geometry.height());
@ -897,35 +897,36 @@ void PaintRow(
+ st::dialogsQuickActionSize / 2.;
p.drawEllipse(QPointF(geometry.width() - offset, offset), r, r);
}
const auto iconOffset = (geometry.height()
- st::dialogsQuickActionSize) / 2;
const auto topTranslation = iconOffset / 2.;
p.translate(0, -topTranslation);
if (context.quickActionContext->icon) {
context.quickActionContext->icon->paint(
const auto quickWidth = st::dialogsQuickActionSize * 3;
DrawQuickAction(
p,
rect::right(geometry)
- iconOffset
- st::dialogsQuickActionSize,
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);
QRect(
rect::right(geometry) - quickWidth,
geometry.y(),
quickWidth,
geometry.height()),
context.quickActionContext->icon.get(),
labelType);
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

View file

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