mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-07-12 00:32:56 +02:00
Make monoforum sender badges float.
This commit is contained in:
parent
7dc8943840
commit
3dbdecf73d
7 changed files with 208 additions and 81 deletions
|
@ -251,7 +251,7 @@ private:
|
|||
// for each found message (in given direction) in the passed history with passed top offset.
|
||||
//
|
||||
// Method has "bool (*Method)(not_null<Element*> view, int itemtop, int itembottom)" signature
|
||||
// if it returns false the enumeration stops immidiately.
|
||||
// if it returns false the enumeration stops immediately.
|
||||
template <EnumItemsDirection direction, typename Method>
|
||||
void enumerateItems(Method method);
|
||||
|
||||
|
|
|
@ -916,6 +916,62 @@ void HistoryInner::enumerateDates(Method method) {
|
|||
enumerateItems<EnumItemsDirection::BottomToTop>(dateCallback);
|
||||
}
|
||||
|
||||
template <typename Method>
|
||||
void HistoryInner::enumerateMonoforumSenders(Method method) {
|
||||
if (!_history->amMonoforumAdmin()) {
|
||||
return;
|
||||
}
|
||||
|
||||
const auto skip = (_scrollDateOpacity.animating() || _scrollDateShown)
|
||||
? int(base::SafeRound(
|
||||
(_scrollDateOpacity.value(_scrollDateShown ? 1. : 0.)
|
||||
* (st::msgServicePadding.bottom()
|
||||
+ st::msgServiceFont->height
|
||||
+ st::msgServicePadding.top()
|
||||
+ st::msgServiceMargin.top()))))
|
||||
: 0;
|
||||
|
||||
// Find and remember the bottom of an single-day messages pack
|
||||
// -1 means we didn't find a same-day with previous message yet.
|
||||
auto lowestInOneBunchItemBottom = -1;
|
||||
|
||||
auto senderCallback = [&](not_null<Element*> view, int itemtop, int itembottom) {
|
||||
const auto item = view->data();
|
||||
if (lowestInOneBunchItemBottom < 0 && view->isInOneBunchWithPrevious()) {
|
||||
lowestInOneBunchItemBottom = itembottom - view->marginBottom();
|
||||
}
|
||||
|
||||
// Call method on a sender for all messages that have it and for those who are not showing it
|
||||
// because they are in a one day together with the previous message if they are top-most visible.
|
||||
if (view->displayMonoforumSender() || (!item->isEmpty() && itemtop <= _visibleAreaTop)) {
|
||||
if (lowestInOneBunchItemBottom < 0) {
|
||||
lowestInOneBunchItemBottom = itembottom - view->marginBottom();
|
||||
}
|
||||
// Attach sender to the top of the visible area with the same margin as it has in service message.
|
||||
int senderTop = qMax(itemtop + view->displayedDateHeight(), _visibleAreaTop + skip) + st::msgServiceMargin.top();
|
||||
|
||||
// Do not let the sender go below the single-sender messages pack bottom line.
|
||||
int senderHeight = st::msgServicePadding.bottom() + st::msgServiceFont->height + st::msgServicePadding.top();
|
||||
senderTop = qMin(senderTop, lowestInOneBunchItemBottom - senderHeight);
|
||||
|
||||
// Call the template callback function that was passed
|
||||
// and return if it finished everything it needed.
|
||||
if (!method(view, itemtop, senderTop)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Forget the found bottom of the pack, search for the next one from scratch.
|
||||
if (!view->isInOneBunchWithPrevious()) {
|
||||
lowestInOneBunchItemBottom = -1;
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
enumerateItems<EnumItemsDirection::BottomToTop>(senderCallback);
|
||||
}
|
||||
|
||||
TextSelection HistoryInner::computeRenderSelection(
|
||||
not_null<const SelectedItems*> selected,
|
||||
not_null<Element*> view) const {
|
||||
|
@ -1291,14 +1347,6 @@ void HistoryInner::paintEvent(QPaintEvent *e) {
|
|||
const auto dateHeight = st::msgServicePadding.bottom()
|
||||
+ st::msgServiceFont->height
|
||||
+ st::msgServicePadding.top();
|
||||
//QDate lastDate;
|
||||
//if (!_history->isEmpty()) {
|
||||
// lastDate = _history->blocks.back()->messages.back()->data()->date.date();
|
||||
//}
|
||||
|
||||
//// if item top is before this value always show date as a floating date
|
||||
//int showFloatingBefore = height() - 2 * (_visibleAreaBottom - _visibleAreaTop) - dateHeight;
|
||||
|
||||
auto scrollDateOpacity = _scrollDateOpacity.value(_scrollDateShown ? 1. : 0.);
|
||||
enumerateDates([&](not_null<Element*> view, int itemtop, int dateTop) {
|
||||
// stop the enumeration if the date is above the painted rect
|
||||
|
@ -1312,21 +1360,13 @@ void HistoryInner::paintEvent(QPaintEvent *e) {
|
|||
const auto correctDateTop = itemtop + st::msgServiceMargin.top();
|
||||
dateInPlace = (dateTop < correctDateTop + dateHeight);
|
||||
}
|
||||
//bool noFloatingDate = (item->date.date() == lastDate && displayDate);
|
||||
//if (noFloatingDate) {
|
||||
// if (itemtop < showFloatingBefore) {
|
||||
// noFloatingDate = false;
|
||||
// }
|
||||
//}
|
||||
|
||||
// paint the date if it intersects the painted rect
|
||||
if (dateTop < clip.top() + clip.height()) {
|
||||
auto opacity = (dateInPlace/* || noFloatingDate*/) ? 1. : scrollDateOpacity;
|
||||
auto opacity = dateInPlace ? 1. : scrollDateOpacity;
|
||||
if (opacity > 0.) {
|
||||
p.setOpacity(opacity);
|
||||
const auto dateY = false // noFloatingDate
|
||||
? itemtop
|
||||
: (dateTop - st::msgServiceMargin.top());
|
||||
const auto dateY = dateTop - st::msgServiceMargin.top();
|
||||
if (const auto date = view->Get<HistoryView::DateBadge>()) {
|
||||
date->paint(p, context.st, dateY, _contentWidth, _isChatWide);
|
||||
} else {
|
||||
|
@ -1344,6 +1384,38 @@ void HistoryInner::paintEvent(QPaintEvent *e) {
|
|||
});
|
||||
p.setOpacity(1.);
|
||||
|
||||
enumerateMonoforumSenders([&](not_null<Element*> view, int itemtop, int senderTop) {
|
||||
// stop the enumeration if the sender is above the painted rect
|
||||
if (senderTop + dateHeight <= clip.top()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const auto displaySender = view->displayMonoforumSender();
|
||||
auto senderInPlace = displaySender;
|
||||
if (senderInPlace) {
|
||||
const auto correctSenderTop = itemtop + view->displayedDateHeight() + st::msgServiceMargin.top();
|
||||
senderInPlace = (senderTop < correctSenderTop + st::msgServiceMargin.top());
|
||||
}
|
||||
|
||||
// paint the sender if it intersects the painted rect
|
||||
if (senderTop < clip.top() + clip.height()) {
|
||||
const auto senderY = senderTop - st::msgServiceMargin.top();
|
||||
if (const auto sender = view->Get<HistoryView::MonoforumSenderBar>()) {
|
||||
sender->paint(p, context.st, senderY, _contentWidth, _isChatWide, !senderInPlace);
|
||||
} else {
|
||||
HistoryView::MonoforumSenderBar::PaintFor(
|
||||
p,
|
||||
context.st,
|
||||
view,
|
||||
_monoforumSenderUserpicView,
|
||||
senderY,
|
||||
_contentWidth,
|
||||
_isChatWide);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
});
|
||||
|
||||
_reactionsManager->paint(p, context);
|
||||
}
|
||||
|
||||
|
@ -3566,6 +3638,9 @@ void HistoryInner::toggleScrollDateShown() {
|
|||
void HistoryInner::repaintScrollDateCallback() {
|
||||
int updateTop = _visibleAreaTop;
|
||||
int updateHeight = st::msgServiceMargin.top() + st::msgServicePadding.top() + st::msgServiceFont->height + st::msgServicePadding.bottom();
|
||||
if (_history->amMonoforumAdmin()) {
|
||||
updateHeight *= 2;
|
||||
}
|
||||
update(0, updateTop, width(), updateHeight);
|
||||
}
|
||||
|
||||
|
|
|
@ -15,6 +15,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "ui/dragging_scroll_manager.h"
|
||||
#include "ui/widgets/tooltip.h"
|
||||
#include "ui/widgets/scroll_area.h"
|
||||
#include "ui/userpic_view.h"
|
||||
#include "history/view/history_view_top_bar_widget.h"
|
||||
|
||||
#include <QtGui/QPainterPath>
|
||||
|
@ -279,7 +280,7 @@ private:
|
|||
// for each found message (in given direction) in the passed history with passed top offset.
|
||||
//
|
||||
// Method has "bool (*Method)(not_null<Element*> view, int itemtop, int itembottom)" signature
|
||||
// if it returns false the enumeration stops immidiately.
|
||||
// if it returns false the enumeration stops immediately.
|
||||
template <bool TopToBottom, typename Method>
|
||||
void enumerateItemsInHistory(History *history, int historytop, Method method);
|
||||
|
||||
|
@ -299,7 +300,7 @@ private:
|
|||
// for each found userpic (from the top to the bottom) using enumerateItems() method.
|
||||
//
|
||||
// Method has "bool (*Method)(not_null<Element*> view, int userpicTop)" signature
|
||||
// if it returns false the enumeration stops immidiately.
|
||||
// if it returns false the enumeration stops immediately.
|
||||
template <typename Method>
|
||||
void enumerateUserpics(Method method);
|
||||
|
||||
|
@ -307,10 +308,18 @@ private:
|
|||
// for each found date element (from the bottom to the top) using enumerateItems() method.
|
||||
//
|
||||
// Method has "bool (*Method)(not_null<Element*> view, int itemtop, int dateTop)" signature
|
||||
// if it returns false the enumeration stops immidiately.
|
||||
// if it returns false the enumeration stops immediately.
|
||||
template <typename Method>
|
||||
void enumerateDates(Method method);
|
||||
|
||||
// This function finds all monoforum sender elements that are displayed and calls template method
|
||||
// for each found date element (from the bottom to the top) using enumerateItems() method.
|
||||
//
|
||||
// Method has "bool (*Method)(not_null<Element*> view, int itemtop, int dateTop)" signature
|
||||
// if it returns false the enumeration stops immediately.
|
||||
template <typename Method>
|
||||
void enumerateMonoforumSenders(Method method);
|
||||
|
||||
void scrollDateCheck();
|
||||
void scrollDateHideByTimer();
|
||||
bool canHaveFromUserpics() const;
|
||||
|
@ -458,6 +467,7 @@ private:
|
|||
int _contentWidth = 0;
|
||||
int _historyPaddingTop = 0;
|
||||
int _revealHeight = 0;
|
||||
Ui::PeerUserpicView _monoforumSenderUserpicView;
|
||||
|
||||
// Save visible area coords for painting / pressing userpics.
|
||||
int _visibleAreaTop = 0;
|
||||
|
|
|
@ -480,7 +480,7 @@ void DateBadge::paint(
|
|||
void MonoforumSenderBar::init(
|
||||
not_null<PeerData*> parentChat,
|
||||
not_null<PeerData*> peer) {
|
||||
author = peer;
|
||||
sender = peer;
|
||||
text.setText(st::semiboldTextStyle, peer->name());
|
||||
const auto skip = st::monoforumBarUserpicSkip;
|
||||
const auto userpic = st::msgServicePadding.top()
|
||||
|
@ -503,8 +503,52 @@ void MonoforumSenderBar::paint(
|
|||
not_null<const Ui::ChatStyle*> st,
|
||||
int y,
|
||||
int w,
|
||||
bool chatWide) const {
|
||||
Expects(author != nullptr);
|
||||
bool chatWide,
|
||||
bool skipPatternLine) const {
|
||||
Paint(p, st, sender, text, width, view, y, w, chatWide, skipPatternLine);
|
||||
}
|
||||
|
||||
void MonoforumSenderBar::PaintFor(
|
||||
Painter &p,
|
||||
not_null<const Ui::ChatStyle*> st,
|
||||
not_null<Element*> itemView,
|
||||
Ui::PeerUserpicView &userpicView,
|
||||
int y,
|
||||
int w,
|
||||
bool chatWide) {
|
||||
const auto sublist = itemView->data()->savedSublist();
|
||||
const auto sender = (sublist && sublist->parentChat())
|
||||
? sublist->sublistPeer().get()
|
||||
: nullptr;
|
||||
if (!sender || sender->isMonoforum()) {
|
||||
return;
|
||||
}
|
||||
auto text = Ui::Text::String(st::semiboldTextStyle, sender->name());
|
||||
const auto skip = st::monoforumBarUserpicSkip;
|
||||
const auto userpic = st::msgServicePadding.top()
|
||||
+ st::msgServiceFont->height
|
||||
+ st::msgServicePadding.bottom()
|
||||
- 2 * skip;
|
||||
const auto width = skip
|
||||
+ userpic
|
||||
+ skip * 2
|
||||
+ text.maxWidth()
|
||||
+ st::msgServicePadding.right();
|
||||
Paint(p, st, sender, text, width, userpicView, y, w, chatWide, true);
|
||||
}
|
||||
|
||||
void MonoforumSenderBar::Paint(
|
||||
Painter &p,
|
||||
not_null<const Ui::ChatStyle*> st,
|
||||
not_null<PeerData*> sender,
|
||||
const Ui::Text::String &text,
|
||||
int width,
|
||||
Ui::PeerUserpicView &view,
|
||||
int y,
|
||||
int w,
|
||||
bool chatWide,
|
||||
bool skipPatternLine) {
|
||||
Expects(sender != nullptr);
|
||||
|
||||
int left = st::msgServiceMargin.left();
|
||||
const auto maxwidth = chatWide
|
||||
|
@ -523,7 +567,7 @@ void MonoforumSenderBar::paint(
|
|||
QRect(left, y + st::msgServiceMargin.top(), use, h));
|
||||
|
||||
const auto skip = st::monoforumBarUserpicSkip;
|
||||
{
|
||||
if (!skipPatternLine) {
|
||||
auto pen = st->msgServiceBg()->p;
|
||||
pen.setWidthF(skip);
|
||||
pen.setCapStyle(Qt::RoundCap);
|
||||
|
@ -540,7 +584,7 @@ void MonoforumSenderBar::paint(
|
|||
- 2 * skip;
|
||||
const auto available = use - (skip + userpic + skip * 2 + st::msgServicePadding.right());
|
||||
|
||||
author->paintUserpic(p, view, left + skip, y + st::msgServiceMargin.top() + skip, userpic);
|
||||
sender->paintUserpic(p, view, left + skip, y + st::msgServiceMargin.top() + skip, userpic);
|
||||
|
||||
p.setFont(st::msgServiceFont);
|
||||
p.setPen(st->msgServiceFg());
|
||||
|
@ -1448,6 +1492,14 @@ bool Element::isInOneDayWithPrevious() const {
|
|||
return !data()->isEmpty() && !displayDate();
|
||||
}
|
||||
|
||||
bool Element::displayMonoforumSender() const {
|
||||
return Has<MonoforumSenderBar>();
|
||||
}
|
||||
|
||||
bool Element::isInOneBunchWithPrevious() const {
|
||||
return !data()->isEmpty() && !displayMonoforumSender();
|
||||
}
|
||||
|
||||
void Element::recountAttachToPreviousInBlocks() {
|
||||
if (isHidden() || data()->isEmpty()) {
|
||||
if (const auto next = nextDisplayedInBlocks()) {
|
||||
|
|
|
@ -268,13 +268,36 @@ struct MonoforumSenderBar : RuntimeComponent<MonoforumSenderBar, Element> {
|
|||
not_null<const Ui::ChatStyle*> st,
|
||||
int y,
|
||||
int w,
|
||||
bool chatWide) const;
|
||||
bool chatWide,
|
||||
bool skipPatternLine) const;
|
||||
static void PaintFor(
|
||||
Painter &p,
|
||||
not_null<const Ui::ChatStyle*> st,
|
||||
not_null<Element*> itemView,
|
||||
Ui::PeerUserpicView &userpicView,
|
||||
int y,
|
||||
int w,
|
||||
bool chatWide);
|
||||
|
||||
PeerData *author = nullptr;
|
||||
PeerData *sender = nullptr;
|
||||
Ui::Text::String text;
|
||||
ClickHandlerPtr link;
|
||||
mutable Ui::PeerUserpicView view;
|
||||
int width = 0;
|
||||
|
||||
private:
|
||||
static void Paint(
|
||||
Painter &p,
|
||||
not_null<const Ui::ChatStyle*> st,
|
||||
not_null<PeerData*> sender,
|
||||
const Ui::Text::String &text,
|
||||
int width,
|
||||
Ui::PeerUserpicView &view,
|
||||
int y,
|
||||
int w,
|
||||
bool chatWide,
|
||||
bool skipPatternLine);
|
||||
|
||||
};
|
||||
|
||||
// Any HistoryView::Element can have this Component for
|
||||
|
@ -438,6 +461,9 @@ public:
|
|||
[[nodiscard]] bool displayDate() const;
|
||||
[[nodiscard]] bool isInOneDayWithPrevious() const;
|
||||
|
||||
[[nodiscard]] bool displayMonoforumSender() const;
|
||||
[[nodiscard]] bool isInOneBunchWithPrevious() const;
|
||||
|
||||
virtual void draw(Painter &p, const PaintContext &context) const = 0;
|
||||
[[nodiscard]] virtual PointState pointState(QPoint point) const = 0;
|
||||
[[nodiscard]] virtual TextState textState(
|
||||
|
|
|
@ -1133,40 +1133,22 @@ void Message::draw(Painter &p, const PaintContext &context) const {
|
|||
|
||||
if (const auto bar = Get<UnreadBar>()) {
|
||||
auto unreadbarh = bar->height();
|
||||
auto dateh = 0;
|
||||
auto aboveh = 0;
|
||||
if (const auto date = Get<DateBadge>()) {
|
||||
dateh = date->height();
|
||||
aboveh += date->height();
|
||||
}
|
||||
if (context.clip.intersects(QRect(0, dateh, width(), unreadbarh))) {
|
||||
p.translate(0, dateh);
|
||||
if (const auto sender = Get<MonoforumSenderBar>()) {
|
||||
aboveh += sender->height();
|
||||
}
|
||||
if (context.clip.intersects(QRect(0, aboveh, width(), unreadbarh))) {
|
||||
p.translate(0, aboveh);
|
||||
bar->paint(
|
||||
p,
|
||||
context,
|
||||
0,
|
||||
width(),
|
||||
delegate()->elementIsChatWide());
|
||||
p.translate(0, -dateh);
|
||||
}
|
||||
}
|
||||
|
||||
if (const auto monoforumBar = Get<MonoforumSenderBar>()) {
|
||||
auto barh = monoforumBar->height();
|
||||
auto skip = 0;
|
||||
if (const auto date = Get<DateBadge>()) {
|
||||
skip += date->height();
|
||||
}
|
||||
if (const auto bar = Get<UnreadBar>()) {
|
||||
skip += bar->height();
|
||||
}
|
||||
if (context.clip.intersects(QRect(0, skip, width(), barh))) {
|
||||
p.translate(0, skip);
|
||||
monoforumBar->paint(
|
||||
p,
|
||||
context.st,
|
||||
0,
|
||||
width(),
|
||||
delegate()->elementIsChatWide());
|
||||
p.translate(0, -skip);
|
||||
p.translate(0, -aboveh);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -547,40 +547,22 @@ void Service::draw(Painter &p, const PaintContext &context) const {
|
|||
const auto st = context.st;
|
||||
if (const auto bar = Get<UnreadBar>()) {
|
||||
auto unreadbarh = bar->height();
|
||||
auto dateh = 0;
|
||||
auto aboveh = 0;
|
||||
if (const auto date = Get<DateBadge>()) {
|
||||
dateh = date->height();
|
||||
aboveh += date->height();
|
||||
}
|
||||
if (context.clip.intersects(QRect(0, dateh, width(), unreadbarh))) {
|
||||
p.translate(0, dateh);
|
||||
if (const auto sender = Get<MonoforumSenderBar>()) {
|
||||
aboveh += sender->height();
|
||||
}
|
||||
if (context.clip.intersects(QRect(0, aboveh, width(), unreadbarh))) {
|
||||
p.translate(0, aboveh);
|
||||
bar->paint(
|
||||
p,
|
||||
context,
|
||||
0,
|
||||
width(),
|
||||
delegate()->elementIsChatWide());
|
||||
p.translate(0, -dateh);
|
||||
}
|
||||
}
|
||||
|
||||
if (const auto monoforumBar = Get<MonoforumSenderBar>()) {
|
||||
auto barh = monoforumBar->height();
|
||||
auto skip = 0;
|
||||
if (const auto date = Get<DateBadge>()) {
|
||||
skip += date->height();
|
||||
}
|
||||
if (const auto bar = Get<UnreadBar>()) {
|
||||
skip += bar->height();
|
||||
}
|
||||
if (context.clip.intersects(QRect(0, skip, width(), barh))) {
|
||||
p.translate(0, skip);
|
||||
monoforumBar->paint(
|
||||
p,
|
||||
context.st,
|
||||
0,
|
||||
width(),
|
||||
delegate()->elementIsChatWide());
|
||||
p.translate(0, -skip);
|
||||
p.translate(0, -aboveh);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue