mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-06-05 22:54:01 +02:00
Show userpics in full who read list.
This commit is contained in:
parent
14314df26a
commit
a3e8e379dd
5 changed files with 169 additions and 22 deletions
|
@ -97,6 +97,13 @@ struct State {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] QImage GenerateUserpic(Userpic &userpic, int size) {
|
||||||
|
size *= style::DevicePixelRatio();
|
||||||
|
auto result = userpic.peer->generateUserpicImage(userpic.view, size);
|
||||||
|
result.setDevicePixelRatio(style::DevicePixelRatio());
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
[[nodiscard]] bool ListUnknown(
|
[[nodiscard]] bool ListUnknown(
|
||||||
const std::vector<PeerId> &list,
|
const std::vector<PeerId> &list,
|
||||||
not_null<HistoryItem*> item) {
|
not_null<HistoryItem*> item) {
|
||||||
|
@ -233,13 +240,9 @@ void RegenerateUserpics(not_null<State*> state, int small, int large) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
participant.userpicKey = userpic.uniqueKey = key;
|
participant.userpicKey = userpic.uniqueKey = key;
|
||||||
participant.userpicLarge = peer->generateUserpicImage(
|
participant.userpicLarge = GenerateUserpic(userpic, large);
|
||||||
userpic.view,
|
|
||||||
large);
|
|
||||||
if (i < Ui::WhoReadParticipant::kMaxSmallUserpics) {
|
if (i < Ui::WhoReadParticipant::kMaxSmallUserpics) {
|
||||||
participant.userpicSmall = peer->generateUserpicImage(
|
participant.userpicSmall = GenerateUserpic(userpic, small);
|
||||||
userpic.view,
|
|
||||||
small);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -259,16 +262,12 @@ void RegenerateParticipants(not_null<State*> state, int small, int large) {
|
||||||
}
|
}
|
||||||
now.push_back({
|
now.push_back({
|
||||||
.name = peer->name,
|
.name = peer->name,
|
||||||
.userpicLarge = peer->generateUserpicImage(
|
.userpicLarge = GenerateUserpic(userpic, large),
|
||||||
userpic.view,
|
|
||||||
large),
|
|
||||||
.userpicKey = userpic.uniqueKey,
|
.userpicKey = userpic.uniqueKey,
|
||||||
.id = id,
|
.id = id,
|
||||||
});
|
});
|
||||||
if (now.size() <= Ui::WhoReadParticipant::kMaxSmallUserpics) {
|
if (now.size() <= Ui::WhoReadParticipant::kMaxSmallUserpics) {
|
||||||
now.back().userpicSmall = peer->generateUserpicImage(
|
now.back().userpicSmall = GenerateUserpic(userpic, small);
|
||||||
userpic.view,
|
|
||||||
small);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
RegenerateUserpics(state, small, large);
|
RegenerateUserpics(state, small, large);
|
||||||
|
|
|
@ -330,7 +330,6 @@ int Launcher::exec() {
|
||||||
|
|
||||||
// Must be started before Sandbox is created.
|
// Must be started before Sandbox is created.
|
||||||
Platform::start();
|
Platform::start();
|
||||||
|
|
||||||
auto result = executeApplication();
|
auto result = executeApplication();
|
||||||
|
|
||||||
DEBUG_LOG(("Telegram finished, result: %1").arg(result));
|
DEBUG_LOG(("Telegram finished, result: %1").arg(result));
|
||||||
|
|
|
@ -1564,7 +1564,11 @@ void HistoryInner::showContextMenu(QContextMenuEvent *e, bool showFromTouch) {
|
||||||
isUponSelected = hasSelected;
|
isUponSelected = hasSelected;
|
||||||
}
|
}
|
||||||
|
|
||||||
_menu = base::make_unique_q<Ui::PopupMenu>(this);
|
const auto hasWhoReadItem = _dragStateItem
|
||||||
|
&& Api::WhoReadExists(_dragStateItem);
|
||||||
|
_menu = base::make_unique_q<Ui::PopupMenu>(
|
||||||
|
this,
|
||||||
|
hasWhoReadItem ? st::whoReadMenu : st::defaultPopupMenu);
|
||||||
const auto session = &this->session();
|
const auto session = &this->session();
|
||||||
const auto controller = _controller;
|
const auto controller = _controller;
|
||||||
const auto groupLeaderOrSelf = [](HistoryItem *item) -> HistoryItem* {
|
const auto groupLeaderOrSelf = [](HistoryItem *item) -> HistoryItem* {
|
||||||
|
@ -1585,13 +1589,13 @@ void HistoryInner::showContextMenu(QContextMenuEvent *e, bool showFromTouch) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const auto itemId = item->fullId();
|
const auto itemId = item->fullId();
|
||||||
if (Api::WhoReadExists(item)) {
|
if (hasWhoReadItem) {
|
||||||
const auto participantChosen = [=](uint64 id) {
|
const auto participantChosen = [=](uint64 id) {
|
||||||
controller->showPeerInfo(PeerId(id));
|
controller->showPeerInfo(PeerId(id));
|
||||||
};
|
};
|
||||||
_menu->addAction(Ui::WhoReadContextAction(
|
_menu->addAction(Ui::WhoReadContextAction(
|
||||||
_menu.get(),
|
_menu.get(),
|
||||||
Api::WhoRead(item, this, st::defaultWhoRead),
|
Api::WhoRead(_dragStateItem, this, st::defaultWhoRead),
|
||||||
participantChosen));
|
participantChosen));
|
||||||
_menu->addSeparator();
|
_menu->addSeparator();
|
||||||
}
|
}
|
||||||
|
|
|
@ -865,7 +865,10 @@ ttlItemTimerFont: font(12px);
|
||||||
|
|
||||||
WhoRead {
|
WhoRead {
|
||||||
userpics: GroupCallUserpics;
|
userpics: GroupCallUserpics;
|
||||||
|
photoLeft: pixels;
|
||||||
photoSize: pixels;
|
photoSize: pixels;
|
||||||
|
photoSkip: pixels;
|
||||||
|
nameLeft: pixels;
|
||||||
itemPadding: margins;
|
itemPadding: margins;
|
||||||
}
|
}
|
||||||
defaultWhoRead: WhoRead {
|
defaultWhoRead: WhoRead {
|
||||||
|
@ -875,6 +878,15 @@ defaultWhoRead: WhoRead {
|
||||||
stroke: 4px;
|
stroke: 4px;
|
||||||
align: align(right);
|
align: align(right);
|
||||||
}
|
}
|
||||||
|
photoLeft: 13px;
|
||||||
photoSize: 30px;
|
photoSize: 30px;
|
||||||
|
photoSkip: 5px;
|
||||||
|
nameLeft: 57px;
|
||||||
itemPadding: margins(17px, 8px, 17px, 6px);
|
itemPadding: margins(17px, 8px, 17px, 6px);
|
||||||
}
|
}
|
||||||
|
whoReadMenu: PopupMenu(defaultPopupMenu) {
|
||||||
|
scrollPadding: margins(0px, 6px, 0px, 6px);
|
||||||
|
menu: Menu(defaultMenu) {
|
||||||
|
separatorPadding: margins(0px, 6px, 0px, 8px);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -17,6 +17,39 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
namespace Ui {
|
namespace Ui {
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
|
struct EntryData {
|
||||||
|
QString text;
|
||||||
|
QImage userpic;
|
||||||
|
Fn<void()> callback;
|
||||||
|
};
|
||||||
|
|
||||||
|
class EntryAction final : public Menu::ItemBase {
|
||||||
|
public:
|
||||||
|
EntryAction(
|
||||||
|
not_null<RpWidget*> parent,
|
||||||
|
const style::Menu &st,
|
||||||
|
EntryData &&data);
|
||||||
|
|
||||||
|
void setData(EntryData &&data);
|
||||||
|
|
||||||
|
not_null<QAction*> action() const override;
|
||||||
|
bool isEnabled() const override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
int contentHeight() const override;
|
||||||
|
|
||||||
|
void paint(Painter &&p);
|
||||||
|
|
||||||
|
const not_null<QAction*> _dummyAction;
|
||||||
|
const style::Menu &_st;
|
||||||
|
const int _height = 0;
|
||||||
|
|
||||||
|
Text::String _text;
|
||||||
|
int _textWidth = 0;
|
||||||
|
QImage _userpic;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
class Action final : public Menu::ItemBase {
|
class Action final : public Menu::ItemBase {
|
||||||
public:
|
public:
|
||||||
Action(
|
Action(
|
||||||
|
@ -50,6 +83,8 @@ private:
|
||||||
const std::unique_ptr<GroupCallUserpics> _userpics;
|
const std::unique_ptr<GroupCallUserpics> _userpics;
|
||||||
const style::Menu &_st;
|
const style::Menu &_st;
|
||||||
|
|
||||||
|
std::vector<not_null<EntryAction*>> _submenuActions;
|
||||||
|
|
||||||
Text::String _text;
|
Text::String _text;
|
||||||
int _textWidth = 0;
|
int _textWidth = 0;
|
||||||
const int _height = 0;
|
const int _height = 0;
|
||||||
|
@ -66,13 +101,88 @@ TextParseOptions MenuTextOptions = {
|
||||||
Qt::LayoutDirectionAuto, // dir
|
Qt::LayoutDirectionAuto, // dir
|
||||||
};
|
};
|
||||||
|
|
||||||
|
EntryAction::EntryAction(
|
||||||
|
not_null<RpWidget*> parent,
|
||||||
|
const style::Menu &st,
|
||||||
|
EntryData &&data)
|
||||||
|
: ItemBase(parent, st)
|
||||||
|
, _dummyAction(CreateChild<QAction>(parent.get()))
|
||||||
|
, _st(st)
|
||||||
|
, _height(st::defaultWhoRead.photoSkip * 2 + st::defaultWhoRead.photoSize) {
|
||||||
|
setAcceptBoth(true);
|
||||||
|
|
||||||
|
initResizeHook(parent->sizeValue());
|
||||||
|
setData(std::move(data));
|
||||||
|
|
||||||
|
paintRequest(
|
||||||
|
) | rpl::start_with_next([=] {
|
||||||
|
paint(Painter(this));
|
||||||
|
}, lifetime());
|
||||||
|
|
||||||
|
enableMouseSelecting();
|
||||||
|
}
|
||||||
|
|
||||||
|
not_null<QAction*> EntryAction::action() const {
|
||||||
|
return _dummyAction.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool EntryAction::isEnabled() const {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
int EntryAction::contentHeight() const {
|
||||||
|
return _height;
|
||||||
|
}
|
||||||
|
|
||||||
|
void EntryAction::setData(EntryData &&data) {
|
||||||
|
setClickedCallback(std::move(data.callback));
|
||||||
|
_userpic = std::move(data.userpic);
|
||||||
|
_text.setMarkedText(_st.itemStyle, { data.text }, MenuTextOptions);
|
||||||
|
const auto textWidth = _text.maxWidth();
|
||||||
|
const auto &padding = _st.itemPadding;
|
||||||
|
const auto goodWidth = st::defaultWhoRead.nameLeft
|
||||||
|
+ textWidth
|
||||||
|
+ padding.right();
|
||||||
|
const auto w = std::clamp(goodWidth, _st.widthMin, _st.widthMax);
|
||||||
|
_textWidth = w - (goodWidth - textWidth);
|
||||||
|
setMinWidth(w);
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
|
||||||
|
void EntryAction::paint(Painter &&p) {
|
||||||
|
const auto enabled = isEnabled();
|
||||||
|
const auto selected = isSelected();
|
||||||
|
if (selected && _st.itemBgOver->c.alpha() < 255) {
|
||||||
|
p.fillRect(0, 0, width(), _height, _st.itemBg);
|
||||||
|
}
|
||||||
|
p.fillRect(0, 0, width(), _height, selected ? _st.itemBgOver : _st.itemBg);
|
||||||
|
if (enabled) {
|
||||||
|
paintRipple(p, 0, 0);
|
||||||
|
}
|
||||||
|
const auto photoSize = st::defaultWhoRead.photoSize;
|
||||||
|
const auto photoTop = (height() - photoSize) / 2;
|
||||||
|
p.drawImage(st::defaultWhoRead.photoLeft, photoTop, _userpic);
|
||||||
|
|
||||||
|
p.setPen(selected
|
||||||
|
? _st.itemFgOver
|
||||||
|
: enabled
|
||||||
|
? _st.itemFg
|
||||||
|
: _st.itemFgDisabled);
|
||||||
|
_text.drawLeftElided(
|
||||||
|
p,
|
||||||
|
st::defaultWhoRead.nameLeft,
|
||||||
|
(height() - _st.itemStyle.font->height) / 2,
|
||||||
|
_textWidth,
|
||||||
|
width());
|
||||||
|
}
|
||||||
|
|
||||||
Action::Action(
|
Action::Action(
|
||||||
not_null<PopupMenu*> parentMenu,
|
not_null<PopupMenu*> parentMenu,
|
||||||
rpl::producer<WhoReadContent> content,
|
rpl::producer<WhoReadContent> content,
|
||||||
Fn<void(uint64)> participantChosen)
|
Fn<void(uint64)> participantChosen)
|
||||||
: ItemBase(parentMenu->menu(), parentMenu->menu()->st())
|
: ItemBase(parentMenu->menu(), parentMenu->menu()->st())
|
||||||
, _parentMenu(parentMenu)
|
, _parentMenu(parentMenu)
|
||||||
, _dummyAction(new QAction(parentMenu->menu()))
|
, _dummyAction(CreateChild<QAction>(parentMenu->menu().get()))
|
||||||
, _participantChosen(std::move(participantChosen))
|
, _participantChosen(std::move(participantChosen))
|
||||||
, _userpics(std::make_unique<GroupCallUserpics>(
|
, _userpics(std::make_unique<GroupCallUserpics>(
|
||||||
st::defaultWhoRead.userpics,
|
st::defaultWhoRead.userpics,
|
||||||
|
@ -155,9 +265,11 @@ void Action::updateUserpicsFromContent() {
|
||||||
const auto count = std::min(
|
const auto count = std::min(
|
||||||
int(_content.participants.size()),
|
int(_content.participants.size()),
|
||||||
WhoReadParticipant::kMaxSmallUserpics);
|
WhoReadParticipant::kMaxSmallUserpics);
|
||||||
|
const auto factor = style::DevicePixelRatio();
|
||||||
users.reserve(count);
|
users.reserve(count);
|
||||||
for (auto i = 0; i != count; ++i) {
|
for (auto i = 0; i != count; ++i) {
|
||||||
const auto &participant = _content.participants[i];
|
auto &participant = _content.participants[i];
|
||||||
|
participant.userpicSmall.setDevicePixelRatio(factor);
|
||||||
users.push_back({
|
users.push_back({
|
||||||
.userpic = participant.userpicSmall,
|
.userpic = participant.userpicSmall,
|
||||||
.userpicKey = participant.userpicKey,
|
.userpicKey = participant.userpicKey,
|
||||||
|
@ -170,19 +282,40 @@ void Action::updateUserpicsFromContent() {
|
||||||
|
|
||||||
void Action::populateSubmenu() {
|
void Action::populateSubmenu() {
|
||||||
if (_content.participants.size() < 2) {
|
if (_content.participants.size() < 2) {
|
||||||
|
_submenuActions.clear();
|
||||||
_parentMenu->removeSubmenu(action());
|
_parentMenu->removeSubmenu(action());
|
||||||
if (!isEnabled()) {
|
if (!isEnabled()) {
|
||||||
setSelected(false);
|
setSelected(false);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto submenu = _parentMenu->ensureSubmenu(action());
|
const auto submenu = _parentMenu->ensureSubmenu(action());
|
||||||
submenu->clearActions();
|
if (_submenuActions.size() > _content.participants.size()) {
|
||||||
|
_submenuActions.clear();
|
||||||
|
submenu->clearActions();
|
||||||
|
}
|
||||||
|
auto index = 0;
|
||||||
for (const auto &participant : _content.participants) {
|
for (const auto &participant : _content.participants) {
|
||||||
const auto chosen = [call = _participantChosen, id = participant.id] {
|
const auto chosen = [call = _participantChosen, id = participant.id] {
|
||||||
call(id);
|
call(id);
|
||||||
};
|
};
|
||||||
submenu->addAction(participant.name, chosen);
|
auto data = EntryData{
|
||||||
|
.text = participant.name,
|
||||||
|
.userpic = participant.userpicLarge,
|
||||||
|
.callback = chosen,
|
||||||
|
};
|
||||||
|
if (index < _submenuActions.size()) {
|
||||||
|
_submenuActions[index]->setData(std::move(data));
|
||||||
|
} else {
|
||||||
|
auto item = base::make_unique_q<EntryAction>(
|
||||||
|
submenu->menu(),
|
||||||
|
_st,
|
||||||
|
std::move(data));
|
||||||
|
_submenuActions.push_back(item.get());
|
||||||
|
submenu->addAction(std::move(item));
|
||||||
|
}
|
||||||
|
++index;
|
||||||
}
|
}
|
||||||
_parentMenu->checkSubmenuShow();
|
_parentMenu->checkSubmenuShow();
|
||||||
}
|
}
|
||||||
|
@ -243,13 +376,13 @@ void Action::refreshDimensions() {
|
||||||
|
|
||||||
const auto goodWidth = padding.left()
|
const auto goodWidth = padding.left()
|
||||||
+ textWidth
|
+ textWidth
|
||||||
+ _userpicsWidth
|
+ (_userpicsWidth ? (_st.itemStyle.font->spacew + _userpicsWidth) : 0)
|
||||||
+ padding.right();
|
+ padding.right();
|
||||||
|
|
||||||
const auto w = std::clamp(
|
const auto w = std::clamp(
|
||||||
goodWidth,
|
goodWidth,
|
||||||
_st.widthMin,
|
_st.widthMin,
|
||||||
_st.widthMax);
|
minWidth());
|
||||||
_textWidth = w - (goodWidth - textWidth);
|
_textWidth = w - (goodWidth - textWidth);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue