chore: paint outline for selected account in ghost picker

This commit is contained in:
AlexeyZavar
2026-04-26 18:54:20 +03:00
parent ba1c274ffb
commit 8cb0f916aa
5 changed files with 73 additions and 19 deletions
Binary file not shown.

After

Width:  |  Height:  |  Size: 444 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 785 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

@@ -13,6 +13,7 @@ using "ui/widgets/widgets.style";
using "dialogs/dialogs.style";
ayuGhostIcon: icon {{ "ayu/ghost", menuIconColor }};
ayuGhostModeGlobalIcon: icon {{ "ayu/ghost_mode_global", historyPeerUserpicFg }};
ayuEditsHistoryIcon: icon {{ "ayu/edits_history", menuIconColor }};
ayuLReadMenuIcon: icon {{ "ayu/lread", menuIconColor }};
ayuSReadMenuIcon: icon {{ "ayu/sread", menuIconColor }};
@@ -20,15 +20,17 @@
#include "main/main_session.h"
#include "settings/settings_builder.h"
#include "settings/settings_common.h"
#include "styles/style_ayu_icons.h"
#include "styles/style_ayu_styles.h"
#include "styles/style_chat.h"
#include "styles/style_chat_helpers.h"
#include "styles/style_layers.h"
#include "styles/style_menu_icons.h"
#include "styles/style_settings.h"
#include "styles/style_window.h"
#include "ui/painter.h"
#include "ui/boxes/single_choice_box.h"
#include "ui/vertical_list.h"
#include "ui/boxes/single_choice_box.h"
#include "ui/text/text.h"
#include "ui/toast/toast.h"
#include "ui/widgets/buttons.h"
@@ -51,16 +53,59 @@ struct GhostPickerState {
Fn<void()> refreshCheckboxes;
};
struct AccountUserpicGeometry {
QRect outer;
QRect inner;
};
[[nodiscard]] AccountUserpicGeometry AccountUserpic(int height) {
const auto line = st::mainMenuAccountLine;
const auto skip = 2 * line + st::lineWidth;
const auto full = st::mainMenuAccountSize + 2 * skip;
const auto outer = QRect(
st::defaultWhoRead.photoLeft
+ (st::defaultWhoRead.photoSize - full) / 2,
(height - full) / 2,
full,
full);
return {
.outer = outer,
.inner = QRect(
outer.x() + skip,
outer.y() + skip,
st::mainMenuAccountSize,
st::mainMenuAccountSize),
};
}
void PaintAccountOutline(Painter &p, QRect outer) {
const auto line = st::mainMenuAccountLine;
const auto shift = st::lineWidth + (line * 0.5);
const auto rect = QRectF(outer).marginsRemoved(QMarginsF(
shift,
shift,
shift,
shift));
auto hq = PainterHighQualityEnabler(p);
auto pen = st::windowBgActive->p;
pen.setWidthF(line);
p.setPen(pen);
p.setBrush(Qt::NoBrush);
AyuUserpic::PaintShape(p, rect);
}
class AccountAction final : public Ui::Menu::ItemBase {
public:
AccountAction(
not_null<Ui::Menu::Menu*> parent,
const style::Menu &st,
UserData *user,
bool active,
Fn<void()> callback)
: ItemBase(parent, st)
, _dummyAction(Ui::CreateChild<QAction>(parent.get()))
, _user(user)
, _active(active)
, _st(st)
, _height(st::defaultWhoRead.photoSkip * 2 + st::defaultWhoRead.photoSize) {
setAcceptBoth(true);
@@ -100,10 +145,17 @@ private:
paintRipple(p, 0, 0);
}
const auto photoSize = st::defaultWhoRead.photoSize;
const auto photoLeft = st::defaultWhoRead.photoLeft;
const auto photoTop = (_height - photoSize) / 2;
_user->paintUserpicLeft(p, _userpicView, photoLeft, photoTop, width(), photoSize);
const auto userpic = AccountUserpic(_height);
_user->paintUserpicLeft(
p,
_userpicView,
userpic.inner.x(),
userpic.inner.y(),
width(),
userpic.inner.width());
if (_active) {
PaintAccountOutline(p, userpic.outer);
}
p.setPen(selected ? _st.itemFgOver : _st.itemFg);
_text.drawLeftElided(
@@ -117,6 +169,7 @@ private:
const not_null<QAction*> _dummyAction;
UserData *_user = nullptr;
mutable Ui::PeerUserpicView _userpicView;
const bool _active = false;
const style::Menu &_st;
Ui::Text::String _text;
const int _height;
@@ -128,9 +181,11 @@ public:
not_null<Ui::Menu::Menu*> parent,
const style::Menu &st,
const QString &text,
bool active,
Fn<void()> callback)
: ItemBase(parent, st)
, _dummyAction(Ui::CreateChild<QAction>(parent.get()))
, _active(active)
, _st(st)
, _height(st::defaultWhoRead.photoSkip * 2 + st::defaultWhoRead.photoSize) {
setAcceptBoth(true);
@@ -170,12 +225,10 @@ private:
paintRipple(p, 0, 0);
}
const auto photoSize = st::defaultWhoRead.photoSize;
const auto photoLeft = st::defaultWhoRead.photoLeft;
const auto photoTop = (_height - photoSize) / 2;
const auto userpic = AccountUserpic(_height);
{
auto hq = PainterHighQualityEnabler(p);
auto rect = QRectF(photoLeft, photoTop, photoSize, photoSize);
auto rect = QRectF(userpic.inner);
auto gradient = QLinearGradient(rect.topLeft(), rect.bottomLeft());
gradient.setStops({
{ 0., st::historyPeer5UserpicBg->c },
@@ -186,16 +239,13 @@ private:
AyuUserpic::PaintShape(p, rect);
}
{
const auto fontsize = (photoSize * 13) / 33;
auto font = st::historyPeerUserpicFont->f;
font.setPixelSize(fontsize);
p.setFont(font);
p.setBrush(Qt::NoBrush);
p.setPen(st::historyPeerUserpicFg);
p.drawText(
QRect(photoLeft, photoTop, photoSize, photoSize),
u"GS"_q,
QTextOption(style::al_center));
auto hq = PainterHighQualityEnabler(p);
p.drawImage(
userpic.inner,
st::ayuGhostModeGlobalIcon.instance(st::historyPeerUserpicFg->c));
}
if (_active) {
PaintAccountOutline(p, userpic.outer);
}
p.setPen(selected ? _st.itemFgOver : _st.itemFg);
@@ -208,6 +258,7 @@ private:
}
const not_null<QAction*> _dummyAction;
const bool _active = false;
const style::Menu &_st;
Ui::Text::String _text;
const int _height;
@@ -530,6 +581,7 @@ void BuildGhostEssentials(SectionBuilder &builder) {
state->menu->menu(),
st::defaultPopupMenu.menu,
tr::ayu_GhostModeGlobalSettings(tr::now),
state->selectedUserId.current() == 0,
[=] { selectGhostProfile(state, 0); }));
for (const auto &account : Core::App().domain().orderedAccounts()) {
@@ -543,6 +595,7 @@ void BuildGhostEssentials(SectionBuilder &builder) {
state->menu->menu(),
st::defaultPopupMenu.menu,
user,
state->selectedUserId.current() == id,
[=] { selectGhostProfile(state, id); }));
}