mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-04-15 21:57:10 +02:00
Add jump-to-topic panel in View as Messages.
This commit is contained in:
parent
8281990bb8
commit
a4e4681835
25 changed files with 470 additions and 150 deletions
|
@ -2213,7 +2213,7 @@ void Updates::feedUpdate(const MTPUpdate &update) {
|
|||
history->requestChatListMessage();
|
||||
if (!history->folderKnown()
|
||||
|| (!history->unreadCountKnown()
|
||||
&& !history->peer->isForum())) {
|
||||
&& !history->isForum())) {
|
||||
history->owner().histories().requestDialogEntry(history);
|
||||
}
|
||||
if (!channel->amCreator()) {
|
||||
|
|
|
@ -86,8 +86,7 @@ forumDialogRow: DialogRow(defaultDialogRow) {
|
|||
forumDialogJumpArrow: icon{{ "dialogs/dialogs_topic_arrow", dialogsTextFg }};
|
||||
forumDialogJumpArrowOver: icon{{ "dialogs/dialogs_topic_arrow", dialogsTextFgOver }};
|
||||
forumDialogJumpArrowSkip: 8px;
|
||||
forumDialogJumpArrowLeft: 3px;
|
||||
forumDialogJumpArrowTop: 3px;
|
||||
forumDialogJumpArrowPosition: point(3px, 3px);
|
||||
forumDialogJumpPadding: margins(8px, 3px, 8px, 3px);
|
||||
forumDialogJumpRadius: 11px;
|
||||
|
||||
|
|
|
@ -571,8 +571,7 @@ void InnerWidget::paintEvent(QPaintEvent *e) {
|
|||
bool mayBeActive) {
|
||||
const auto key = row->key();
|
||||
const auto active = mayBeActive && (activeEntry.key == key);
|
||||
const auto forum = key.history()
|
||||
&& key.history()->peer->isForum();
|
||||
const auto forum = key.history() && key.history()->isForum();
|
||||
if (forum && !_topicJumpCache) {
|
||||
_topicJumpCache = std::make_unique<Ui::TopicJumpCache>();
|
||||
}
|
||||
|
|
|
@ -264,7 +264,7 @@ Row::Row(Key key, int index, int top) : _id(key), _top(top), _index(index) {
|
|||
|
||||
void Row::recountHeight(float64 narrowRatio) {
|
||||
if (const auto history = _id.history()) {
|
||||
_height = history->peer->isForum()
|
||||
_height = history->isForum()
|
||||
? anim::interpolate(
|
||||
st::forumDialogRow.height,
|
||||
st::defaultDialogRow.height,
|
||||
|
|
|
@ -455,7 +455,7 @@ void Widget::chosenRow(const ChosenRow &row) {
|
|||
topic,
|
||||
row.message.fullId.msg,
|
||||
Window::SectionShow::Way::ClearStack);
|
||||
} else if (history && history->peer->isForum() && !row.message.fullId) {
|
||||
} else if (history && history->isForum() && !row.message.fullId) {
|
||||
const auto forum = history->peer->forum();
|
||||
if (controller()->shownForum().current() == forum) {
|
||||
controller()->closeForum();
|
||||
|
@ -1916,7 +1916,7 @@ void Widget::dropEvent(QDropEvent *e) {
|
|||
controller()->content()->filesOrForwardDrop(
|
||||
thread,
|
||||
e->mimeData());
|
||||
if (!thread->owningHistory()->peer->isForum()) {
|
||||
if (!thread->owningHistory()->isForum()) {
|
||||
hideChildList();
|
||||
}
|
||||
controller()->widget()->raise();
|
||||
|
|
|
@ -56,7 +56,7 @@ const auto kPsaBadgePrefix = "cloud_lng_badge_psa_";
|
|||
} else if (const auto user = history->peer->asUser()) {
|
||||
return (user->onlineTill > 0);
|
||||
}
|
||||
return !history->peer->isForum();
|
||||
return !history->isForum();
|
||||
}
|
||||
|
||||
void PaintRowTopRight(
|
||||
|
|
|
@ -326,14 +326,11 @@ void MessageView::paint(
|
|||
rect.setLeft(rect.x() + _textCache.maxWidth());
|
||||
}
|
||||
if (jump1) {
|
||||
const auto x = (rect.width() > 0)
|
||||
? rect.x()
|
||||
: finalRight;
|
||||
const auto add = st::forumDialogJumpArrowLeft;
|
||||
const auto y = rect.y() + st::forumDialogJumpArrowTop;
|
||||
const auto position = st::forumDialogJumpArrowPosition
|
||||
+ QPoint((rect.width() > 0) ? rect.x() : finalRight, rect.y());
|
||||
(context.selected
|
||||
? st::forumDialogJumpArrowOver
|
||||
: st::forumDialogJumpArrow).paint(p, x + add, y, context.width);
|
||||
: st::forumDialogJumpArrow).paint(p, position, context.width);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1271,7 +1271,7 @@ void History::newItemAdded(not_null<HistoryItem*> item) {
|
|||
if (item->unread(this)) {
|
||||
if (unreadCountKnown()) {
|
||||
setUnreadCount(unreadCount() + 1);
|
||||
} else if (!peer->isForum()) {
|
||||
} else if (!isForum()) {
|
||||
owner().histories().requestDialogEntry(this);
|
||||
}
|
||||
} else {
|
||||
|
@ -1800,7 +1800,7 @@ void History::setUnreadCount(int newUnreadCount) {
|
|||
if (_unreadCount == newUnreadCount) {
|
||||
return;
|
||||
}
|
||||
const auto notifier = unreadStateChangeNotifier(!peer->isForum());
|
||||
const auto notifier = unreadStateChangeNotifier(!isForum());
|
||||
_unreadCount = newUnreadCount;
|
||||
|
||||
const auto lastOutgoing = [&] {
|
||||
|
@ -1839,7 +1839,7 @@ void History::setUnreadMark(bool unread) {
|
|||
return;
|
||||
}
|
||||
const auto notifier = unreadStateChangeNotifier(
|
||||
!unreadCount() && !peer->isForum());
|
||||
!unreadCount() && !isForum());
|
||||
Thread::setUnreadMarkFlag(unread);
|
||||
}
|
||||
|
||||
|
@ -1871,7 +1871,7 @@ void History::setMuted(bool muted) {
|
|||
if (this->muted() == muted) {
|
||||
return;
|
||||
} else {
|
||||
const auto state = peer->isForum()
|
||||
const auto state = isForum()
|
||||
? Dialogs::BadgesState()
|
||||
: computeBadgesState();
|
||||
const auto notify = (state.unread || state.reaction);
|
||||
|
@ -1984,7 +1984,7 @@ int History::chatListNameVersion() const {
|
|||
}
|
||||
|
||||
void History::hasUnreadMentionChanged(bool has) {
|
||||
if (peer->isForum()) {
|
||||
if (isForum()) {
|
||||
return;
|
||||
}
|
||||
auto was = chatListUnreadState();
|
||||
|
@ -1997,7 +1997,7 @@ void History::hasUnreadMentionChanged(bool has) {
|
|||
}
|
||||
|
||||
void History::hasUnreadReactionChanged(bool has) {
|
||||
if (peer->isForum()) {
|
||||
if (isForum()) {
|
||||
return;
|
||||
}
|
||||
auto was = chatListUnreadState();
|
||||
|
@ -2966,18 +2966,22 @@ HistoryItem *History::lastEditableMessage() const {
|
|||
}
|
||||
|
||||
void History::resizeToWidth(int newWidth) {
|
||||
const auto resizeAllItems = (_width != newWidth);
|
||||
|
||||
if (!resizeAllItems && !hasPendingResizedItems()) {
|
||||
using Request = HistoryBlock::ResizeRequest;
|
||||
const auto request = (_flags & Flag::PendingAllItemsResize)
|
||||
? Request::ReinitAll
|
||||
: (_width != newWidth)
|
||||
? Request::ResizeAll
|
||||
: Request::ResizePending;
|
||||
if (request == Request::ResizePending && !hasPendingResizedItems()) {
|
||||
return;
|
||||
}
|
||||
_flags &= ~(Flag::HasPendingResizedItems);
|
||||
_flags &= ~(Flag::HasPendingResizedItems | Flag::PendingAllItemsResize);
|
||||
|
||||
_width = newWidth;
|
||||
int y = 0;
|
||||
for (const auto &block : blocks) {
|
||||
block->setY(y);
|
||||
y += block->resizeGetHeight(newWidth, resizeAllItems);
|
||||
y += block->resizeGetHeight(newWidth, request);
|
||||
}
|
||||
_height = y;
|
||||
}
|
||||
|
@ -3024,6 +3028,11 @@ void History::forumChanged(Data::Forum *old) {
|
|||
if (cloudDraft(MsgId(0))) {
|
||||
updateChatListSortPosition();
|
||||
}
|
||||
_flags |= Flag::PendingAllItemsResize;
|
||||
}
|
||||
|
||||
bool History::isForum() const {
|
||||
return (_flags & Flag::IsForum);
|
||||
}
|
||||
|
||||
not_null<History*> History::migrateToOrMe() const {
|
||||
|
@ -3441,14 +3450,25 @@ HistoryBlock::HistoryBlock(not_null<History*> history)
|
|||
: _history(history) {
|
||||
}
|
||||
|
||||
int HistoryBlock::resizeGetHeight(int newWidth, bool resizeAllItems) {
|
||||
int HistoryBlock::resizeGetHeight(int newWidth, ResizeRequest request) {
|
||||
auto y = 0;
|
||||
for (const auto &message : messages) {
|
||||
message->setY(y);
|
||||
if (resizeAllItems || message->pendingResize()) {
|
||||
if (request == ResizeRequest::ReinitAll) {
|
||||
for (const auto &message : messages) {
|
||||
message->setY(y);
|
||||
message->initDimensions();
|
||||
y += message->resizeGetHeight(newWidth);
|
||||
} else {
|
||||
y += message->height();
|
||||
}
|
||||
} else if (request == ResizeRequest::ResizeAll) {
|
||||
for (const auto &message : messages) {
|
||||
message->setY(y);
|
||||
y += message->resizeGetHeight(newWidth);
|
||||
}
|
||||
} else {
|
||||
for (const auto &message : messages) {
|
||||
message->setY(y);
|
||||
y += message->pendingResize()
|
||||
? message->resizeGetHeight(newWidth)
|
||||
: message->height();
|
||||
}
|
||||
}
|
||||
_height = y;
|
||||
|
|
|
@ -94,6 +94,7 @@ public:
|
|||
}
|
||||
|
||||
void forumChanged(Data::Forum *old);
|
||||
[[nodiscard]] bool isForum() const;
|
||||
|
||||
not_null<History*> migrateToOrMe() const;
|
||||
History *migrateFrom() const;
|
||||
|
@ -462,10 +463,11 @@ private:
|
|||
|
||||
enum class Flag : uchar {
|
||||
HasPendingResizedItems = (1 << 0),
|
||||
IsTopPromoted = (1 << 1),
|
||||
IsForum = (1 << 2),
|
||||
FakeUnreadWhileOpened = (1 << 3),
|
||||
HasPinnedMessages = (1 << 4),
|
||||
PendingAllItemsResize = (1 << 1),
|
||||
IsTopPromoted = (1 << 2),
|
||||
IsForum = (1 << 3),
|
||||
FakeUnreadWhileOpened = (1 << 4),
|
||||
HasPinnedMessages = (1 << 5),
|
||||
};
|
||||
using Flags = base::flags<Flag>;
|
||||
friend inline constexpr auto is_flag_type(Flag) {
|
||||
|
@ -636,12 +638,18 @@ private:
|
|||
|
||||
HistoryView::SendActionPainter _sendActionPainter;
|
||||
|
||||
};
|
||||
};
|
||||
|
||||
class HistoryBlock {
|
||||
public:
|
||||
using Element = HistoryView::Element;
|
||||
|
||||
enum class ResizeRequest {
|
||||
ReinitAll = 0,
|
||||
ResizeAll = 1,
|
||||
ResizePending = 2,
|
||||
};
|
||||
|
||||
HistoryBlock(not_null<History*> history);
|
||||
HistoryBlock(const HistoryBlock &) = delete;
|
||||
HistoryBlock &operator=(const HistoryBlock &) = delete;
|
||||
|
@ -652,7 +660,7 @@ public:
|
|||
void remove(not_null<Element*> view);
|
||||
void refreshView(not_null<Element*> view);
|
||||
|
||||
int resizeGetHeight(int newWidth, bool resizeAllItems);
|
||||
int resizeGetHeight(int newWidth, ResizeRequest request);
|
||||
int y() const {
|
||||
return _y;
|
||||
}
|
||||
|
|
|
@ -227,7 +227,7 @@ public:
|
|||
return _widget ? _widget->elementAnimationsPaused() : false;
|
||||
}
|
||||
bool elementHideReply(not_null<const Element*> view) override {
|
||||
return false;
|
||||
return view->isTopicRootReply();
|
||||
}
|
||||
bool elementShownUnread(not_null<const Element*> view) override {
|
||||
return view->data()->unread(view->data()->history());
|
||||
|
@ -2096,7 +2096,7 @@ void HistoryInner::showContextMenu(QContextMenuEvent *e, bool showFromTouch) {
|
|||
}
|
||||
const auto repliesCount = item->repliesCount();
|
||||
const auto withReplies = (repliesCount > 0);
|
||||
const auto topicRootId = item->history()->peer->isForum()
|
||||
const auto topicRootId = item->history()->isForum()
|
||||
? item->topicRootId()
|
||||
: 0;
|
||||
if (topicRootId
|
||||
|
|
|
@ -775,7 +775,7 @@ void HistoryItem::setRealId(MsgId newId) {
|
|||
}
|
||||
|
||||
_history->owner().notifyItemDataChange(this);
|
||||
_history->owner().requestItemRepaint(this);
|
||||
_history->owner().requestItemResize(this);
|
||||
}
|
||||
|
||||
bool HistoryItem::canPin() const {
|
||||
|
|
|
@ -2971,7 +2971,7 @@ void HistoryWidget::unreadCountUpdated() {
|
|||
}
|
||||
});
|
||||
} else {
|
||||
_cornerButtons.updateJumpDownVisibility(_history->peer->isForum()
|
||||
_cornerButtons.updateJumpDownVisibility(_history->isForum()
|
||||
? 0
|
||||
: _history->chatListBadgesState().unreadCounter);
|
||||
}
|
||||
|
@ -5991,7 +5991,7 @@ void HistoryWidget::handlePeerMigration() {
|
|||
}
|
||||
|
||||
bool HistoryWidget::replyToPreviousMessage() {
|
||||
if (!_history || _editMsgId || _history->peer->isForum()) {
|
||||
if (!_history || _editMsgId || _history->isForum()) {
|
||||
return false;
|
||||
}
|
||||
const auto fullId = FullMsgId(_history->peer->id, _replyToId);
|
||||
|
@ -6014,7 +6014,7 @@ bool HistoryWidget::replyToPreviousMessage() {
|
|||
}
|
||||
|
||||
bool HistoryWidget::replyToNextMessage() {
|
||||
if (!_history || _editMsgId || _history->peer->isForum()) {
|
||||
if (!_history || _editMsgId || _history->isForum()) {
|
||||
return false;
|
||||
}
|
||||
const auto fullId = FullMsgId(_history->peer->id, _replyToId);
|
||||
|
|
|
@ -617,7 +617,7 @@ bool AddViewRepliesAction(
|
|||
|| (context != Context::History && context != Context::Pinned)) {
|
||||
return false;
|
||||
}
|
||||
const auto topicRootId = item->history()->peer->isForum()
|
||||
const auto topicRootId = item->history()->isForum()
|
||||
? item->topicRootId()
|
||||
: 0;
|
||||
const auto repliesCount = item->repliesCount();
|
||||
|
|
|
@ -566,6 +566,10 @@ bool Element::isBubbleAttachedToNext() const {
|
|||
return _flags & Flag::BubbleAttachedToNext;
|
||||
}
|
||||
|
||||
bool Element::isTopicRootReply() const {
|
||||
return _flags & Flag::TopicRootReply;
|
||||
}
|
||||
|
||||
int Element::skipBlockWidth() const {
|
||||
return st::msgDateSpace + infoWidth() - st::msgDateDelta.x();
|
||||
}
|
||||
|
@ -905,7 +909,8 @@ bool Element::computeIsAttachToPrevious(not_null<Element*> previous) {
|
|||
< kAttachMessageToPreviousSecondsDelta)
|
||||
&& mayBeAttached(this)
|
||||
&& mayBeAttached(previous)
|
||||
&& (!previousMarkup || previousMarkup->hiddenBy(prev->media()));
|
||||
&& (!previousMarkup || previousMarkup->hiddenBy(prev->media()))
|
||||
&& (item->topicRootId() == prev->topicRootId());
|
||||
if (possible) {
|
||||
const auto forwarded = item->Get<HistoryMessageForwarded>();
|
||||
const auto prevForwarded = prev->Get<HistoryMessageForwarded>();
|
||||
|
@ -1068,17 +1073,35 @@ void Element::recountDisplayDateInBlocks() {
|
|||
}
|
||||
|
||||
QSize Element::countOptimalSize() {
|
||||
_flags &= ~Flag::NeedsResize;
|
||||
return performCountOptimalSize();
|
||||
}
|
||||
|
||||
QSize Element::countCurrentSize(int newWidth) {
|
||||
if (_flags & Flag::NeedsResize) {
|
||||
_flags &= ~Flag::NeedsResize;
|
||||
initDimensions();
|
||||
}
|
||||
return performCountCurrentSize(newWidth);
|
||||
}
|
||||
|
||||
void Element::refreshIsTopicRootReply() {
|
||||
const auto topicRootReply = countIsTopicRootReply();
|
||||
if (topicRootReply) {
|
||||
_flags |= Flag::TopicRootReply;
|
||||
} else {
|
||||
_flags &= ~Flag::TopicRootReply;
|
||||
}
|
||||
}
|
||||
|
||||
bool Element::countIsTopicRootReply() const {
|
||||
const auto item = data();
|
||||
if (!item->history()->isForum()) {
|
||||
return false;
|
||||
}
|
||||
const auto replyTo = item->replyToId();
|
||||
return !replyTo || (item->topicRootId() == replyTo);
|
||||
}
|
||||
|
||||
void Element::setDisplayDate(bool displayDate) {
|
||||
const auto item = data();
|
||||
if (displayDate && !Has<DateBadge>()) {
|
||||
|
@ -1156,6 +1179,10 @@ bool Element::displayFromName() const {
|
|||
return false;
|
||||
}
|
||||
|
||||
bool Element::displayTopicButton() const {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Element::displayForwardedFrom() const {
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -254,6 +254,7 @@ public:
|
|||
SpecialOnlyEmoji = 0x0080,
|
||||
CustomEmojiRepainting = 0x0100,
|
||||
ScheduledUntilOnline = 0x0200,
|
||||
TopicRootReply = 0x0400,
|
||||
};
|
||||
using Flags = base::flags<Flag>;
|
||||
friend inline constexpr auto is_flag_type(Flag) { return true; }
|
||||
|
@ -290,6 +291,8 @@ public:
|
|||
[[nodiscard]] bool isBubbleAttachedToPrevious() const;
|
||||
[[nodiscard]] bool isBubbleAttachedToNext() const;
|
||||
|
||||
[[nodiscard]] bool isTopicRootReply() const;
|
||||
|
||||
[[nodiscard]] int skipBlockWidth() const;
|
||||
[[nodiscard]] int skipBlockHeight() const;
|
||||
[[nodiscard]] virtual int infoWidth() const;
|
||||
|
@ -373,6 +376,7 @@ public:
|
|||
[[nodiscard]] virtual bool displayFromPhoto() const;
|
||||
[[nodiscard]] virtual bool hasFromName() const;
|
||||
[[nodiscard]] virtual bool displayFromName() const;
|
||||
[[nodiscard]] virtual bool displayTopicButton() const;
|
||||
[[nodiscard]] virtual bool displayForwardedFrom() const;
|
||||
[[nodiscard]] virtual bool hasOutLayout() const;
|
||||
[[nodiscard]] virtual bool drawBubble() const;
|
||||
|
@ -497,6 +501,7 @@ protected:
|
|||
|
||||
void clearSpecialOnlyEmoji();
|
||||
void checkSpecialOnlyEmoji();
|
||||
void refreshIsTopicRootReply();
|
||||
|
||||
private:
|
||||
// This should be called only from previousInBlocksChanged()
|
||||
|
@ -510,6 +515,8 @@ private:
|
|||
// HistoryView::Element::Flag::AttachedToPrevious.
|
||||
void recountAttachToPreviousInBlocks();
|
||||
|
||||
[[nodiscard]] bool countIsTopicRootReply() const;
|
||||
|
||||
QSize countOptimalSize() final override;
|
||||
QSize countCurrentSize(int newWidth) final override;
|
||||
|
||||
|
|
|
@ -8,6 +8,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "history/view/history_view_message.h"
|
||||
|
||||
#include "core/click_handler_types.h" // ClickHandlerContext
|
||||
#include "core/ui_integration.h"
|
||||
#include "history/view/history_view_cursor_state.h"
|
||||
#include "history/history_item_components.h"
|
||||
#include "history/history_message.h"
|
||||
|
@ -225,6 +226,23 @@ QString FastReplyText() {
|
|||
return tr::lng_fast_reply(tr::now);
|
||||
}
|
||||
|
||||
[[nodiscard]] ClickHandlerPtr MakeTopicButtonLink(
|
||||
not_null<Data::ForumTopic*> topic,
|
||||
MsgId messageId) {
|
||||
const auto weak = base::make_weak(topic);
|
||||
return std::make_shared<LambdaClickHandler>([=](ClickContext context) {
|
||||
const auto my = context.other.value<ClickHandlerContext>();
|
||||
if (const auto controller = my.sessionWindow.get()) {
|
||||
if (const auto strong = weak.get()) {
|
||||
controller->showTopic(
|
||||
strong,
|
||||
messageId,
|
||||
Window::SectionShow::Way::Forward);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
style::color FromNameFg(
|
||||
|
@ -260,11 +278,19 @@ style::color FromNameFg(
|
|||
|
||||
struct Message::CommentsButton {
|
||||
std::unique_ptr<Ui::RippleAnimation> ripple;
|
||||
int rippleShift = 0;
|
||||
std::vector<UserpicInRow> userpics;
|
||||
QImage cachedUserpics;
|
||||
ClickHandlerPtr link;
|
||||
QPoint lastPoint;
|
||||
int rippleShift = 0;
|
||||
};
|
||||
|
||||
struct Message::TopicButton {
|
||||
std::unique_ptr<Ui::RippleAnimation> ripple;
|
||||
ClickHandlerPtr link;
|
||||
Ui::Text::String name;
|
||||
QPoint lastPoint;
|
||||
int nameVersion = 0;
|
||||
};
|
||||
|
||||
struct Message::FromNameStatus {
|
||||
|
@ -488,9 +514,11 @@ auto Message::takeReactionAnimations()
|
|||
QSize Message::performCountOptimalSize() {
|
||||
const auto item = message();
|
||||
const auto markup = item->inlineReplyMarkup();
|
||||
refreshIsTopicRootReply();
|
||||
validateText();
|
||||
validateInlineKeyboard(markup);
|
||||
updateViewButtonExistence();
|
||||
refreshTopicButton();
|
||||
updateMediaInBubbleState();
|
||||
refreshRightBadge();
|
||||
refreshInfoSkipBlock();
|
||||
|
@ -614,6 +642,15 @@ QSize Message::performCountOptimalSize() {
|
|||
} else if (via && !displayForwardedFrom()) {
|
||||
accumulate_max(maxWidth, st::msgPadding.left() + via->maxWidth + st::msgPadding.right());
|
||||
}
|
||||
if (displayTopicButton()) {
|
||||
const auto padding = st::msgPadding + st::topicButtonPadding;
|
||||
accumulate_max(
|
||||
maxWidth,
|
||||
(padding.left()
|
||||
+ _topicButton->name.maxWidth()
|
||||
+ st::topicButtonArrowSkip
|
||||
+ padding.right()));
|
||||
}
|
||||
if (displayForwardedFrom()) {
|
||||
const auto skip1 = forwarded->psaType.isEmpty()
|
||||
? 0
|
||||
|
@ -653,6 +690,34 @@ QSize Message::performCountOptimalSize() {
|
|||
return QSize(maxWidth, minHeight);
|
||||
}
|
||||
|
||||
void Message::refreshTopicButton() {
|
||||
const auto item = message();
|
||||
if (isAttachedToPrevious() || context() != Context::History) {
|
||||
_topicButton = nullptr;
|
||||
} else if (const auto topic = item->topic()) {
|
||||
if (!_topicButton) {
|
||||
_topicButton = std::make_unique<TopicButton>();
|
||||
}
|
||||
const auto jumpToId = IsServerMsgId(item->id) ? item->id : MsgId();
|
||||
_topicButton->link = MakeTopicButtonLink(topic, jumpToId);
|
||||
if (_topicButton->nameVersion != topic->titleVersion()) {
|
||||
_topicButton->nameVersion = topic->titleVersion();
|
||||
const auto context = Core::MarkedTextContext{
|
||||
.session = &history()->session(),
|
||||
.customEmojiRepaint = [=] { customEmojiRepaint(); },
|
||||
.customEmojiLoopLimit = 1,
|
||||
};
|
||||
_topicButton->name.setMarkedText(
|
||||
st::fwdTextStyle,
|
||||
topic->titleWithIcon(),
|
||||
kMarkupTextOptions,
|
||||
context);
|
||||
}
|
||||
} else {
|
||||
_topicButton = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
int Message::marginTop() const {
|
||||
auto result = 0;
|
||||
if (!isHidden()) {
|
||||
|
@ -869,6 +934,7 @@ void Message::draw(Painter &p, const PaintContext &context) const {
|
|||
trect.setY(trect.y() - st::msgPadding.top());
|
||||
} else {
|
||||
paintFromName(p, trect, context);
|
||||
paintTopicButton(p, trect, context);
|
||||
paintForwardedInfo(p, trect, context);
|
||||
paintReplyInfo(p, trect, context);
|
||||
paintViaBotIdInfo(p, trect, context);
|
||||
|
@ -1233,6 +1299,71 @@ void Message::paintFromName(
|
|||
trect.setY(trect.y() + st::msgNameFont->height);
|
||||
}
|
||||
|
||||
void Message::paintTopicButton(
|
||||
Painter &p,
|
||||
QRect &trect,
|
||||
const PaintContext &context) const {
|
||||
if (!displayTopicButton()) {
|
||||
return;
|
||||
}
|
||||
trect.setTop(trect.top() + st::topicButtonSkip);
|
||||
const auto padding = st::topicButtonPadding;
|
||||
const auto availableWidth = trect.width();
|
||||
const auto height = padding.top()
|
||||
+ st::msgNameFont->height
|
||||
+ padding.bottom();
|
||||
const auto width = std::max(
|
||||
std::min(
|
||||
availableWidth,
|
||||
(padding.left()
|
||||
+ _topicButton->name.maxWidth()
|
||||
+ st::topicButtonArrowSkip
|
||||
+ padding.right())),
|
||||
height);
|
||||
const auto rect = QRect(trect.x(), trect.y(), width, height);
|
||||
|
||||
const auto st = context.st;
|
||||
const auto stm = context.messageStyle();
|
||||
const auto skip = padding.right() + st::topicButtonArrowSkip;
|
||||
auto color = stm->msgServiceFg->c;
|
||||
color.setAlpha(color.alpha() / 8);
|
||||
p.setPen(Qt::NoPen);
|
||||
p.setBrush(color);
|
||||
{
|
||||
auto hq = PainterHighQualityEnabler(p);
|
||||
p.drawRoundedRect(rect, height / 2, height / 2);
|
||||
}
|
||||
if (_topicButton->ripple) {
|
||||
_topicButton->ripple->paint(
|
||||
p,
|
||||
rect.x(),
|
||||
rect.y(),
|
||||
this->width(),
|
||||
&color);
|
||||
if (_topicButton->ripple->empty()) {
|
||||
_topicButton->ripple.reset();
|
||||
}
|
||||
}
|
||||
clearCustomEmojiRepaint();
|
||||
p.setPen(stm->msgServiceFg);
|
||||
p.setTextPalette(stm->fwdTextPalette);
|
||||
_topicButton->name.drawElided(
|
||||
p,
|
||||
trect.x() + padding.left(),
|
||||
trect.y() + padding.top(),
|
||||
width - padding.left() - skip);
|
||||
|
||||
const auto &icon = st::topicButtonArrow;
|
||||
icon.paint(
|
||||
p,
|
||||
rect.x() + rect.width() - skip + st::topicButtonArrowPosition.x(),
|
||||
rect.y() + padding.top() + st::topicButtonArrowPosition.y(),
|
||||
this->width(),
|
||||
stm->msgServiceFg->c);
|
||||
|
||||
trect.setY(trect.y() + height + st::topicButtonSkip);
|
||||
}
|
||||
|
||||
void Message::paintForwardedInfo(
|
||||
Painter &p,
|
||||
QRect &trect,
|
||||
|
@ -1388,6 +1519,7 @@ PointState Message::pointState(QPoint point) const {
|
|||
// trect.setY(trect.y() - st::msgPadding.top());
|
||||
//} else {
|
||||
// if (getStateFromName(point, trect, &result)) return result;
|
||||
// if (getStateTopicButton(point, trect, &result)) return result;
|
||||
// if (getStateForwardedInfo(point, trect, &result, request)) return result;
|
||||
// if (getStateReplyInfo(point, trect, &result)) return result;
|
||||
// if (getStateViaBotIdInfo(point, trect, &result)) return result;
|
||||
|
@ -1432,6 +1564,8 @@ void Message::clickHandlerPressedChanged(
|
|||
return;
|
||||
} else if (_comments && (handler == _comments->link)) {
|
||||
toggleCommentsButtonRipple(pressed);
|
||||
} else if (_topicButton && (handler == _topicButton->link)) {
|
||||
toggleTopicButtonRipple(pressed);
|
||||
} else if (_viewButton) {
|
||||
_viewButton->checkLink(handler, pressed);
|
||||
}
|
||||
|
@ -1444,7 +1578,7 @@ void Message::toggleCommentsButtonRipple(bool pressed) {
|
|||
return;
|
||||
} else if (pressed) {
|
||||
if (!_comments->ripple) {
|
||||
createCommentsRipple();
|
||||
createCommentsButtonRipple();
|
||||
}
|
||||
_comments->ripple->add(_comments->lastPoint
|
||||
+ QPoint(_comments->rippleShift, 0));
|
||||
|
@ -1522,7 +1656,7 @@ BottomRippleMask Message::bottomRippleMask(int buttonHeight) const {
|
|||
};
|
||||
}
|
||||
|
||||
void Message::createCommentsRipple() {
|
||||
void Message::createCommentsButtonRipple() {
|
||||
auto mask = bottomRippleMask(st::historyCommentsButtonHeight);
|
||||
_comments->ripple = std::make_unique<Ui::RippleAnimation>(
|
||||
st::defaultRippleAnimation,
|
||||
|
@ -1531,6 +1665,45 @@ void Message::createCommentsRipple() {
|
|||
_comments->rippleShift = mask.shift;
|
||||
}
|
||||
|
||||
void Message::toggleTopicButtonRipple(bool pressed) {
|
||||
Expects(_topicButton != nullptr);
|
||||
|
||||
if (!drawBubble()) {
|
||||
return;
|
||||
} else if (pressed) {
|
||||
if (!_topicButton->ripple) {
|
||||
createTopicButtonRipple();
|
||||
}
|
||||
_topicButton->ripple->add(_topicButton->lastPoint);
|
||||
} else if (_topicButton->ripple) {
|
||||
_topicButton->ripple->lastStop();
|
||||
}
|
||||
}
|
||||
|
||||
void Message::createTopicButtonRipple() {
|
||||
const auto geometry = countGeometry().marginsRemoved(st::msgPadding);
|
||||
const auto availableWidth = geometry.width();
|
||||
const auto padding = st::topicButtonPadding;
|
||||
const auto height = padding.top()
|
||||
+ st::msgNameFont->height
|
||||
+ padding.bottom();
|
||||
const auto width = std::max(
|
||||
std::min(
|
||||
availableWidth,
|
||||
(padding.left()
|
||||
+ _topicButton->name.maxWidth()
|
||||
+ st::topicButtonArrowSkip
|
||||
+ padding.right())),
|
||||
height);
|
||||
auto mask = Ui::RippleAnimation::RoundRectMask(
|
||||
{ width, height },
|
||||
height / 2);
|
||||
_topicButton->ripple = std::make_unique<Ui::RippleAnimation>(
|
||||
st::defaultRippleAnimation,
|
||||
std::move(mask),
|
||||
[=] { repaint(); });
|
||||
}
|
||||
|
||||
bool Message::hasHeavyPart() const {
|
||||
return _comments
|
||||
|| (_fromNameStatus && _fromNameStatus->custom)
|
||||
|
@ -1692,6 +1865,9 @@ TextState Message::textState(
|
|||
if (getStateFromName(point, trect, &result)) {
|
||||
return result;
|
||||
}
|
||||
if (getStateTopicButton(point, trect, &result)) {
|
||||
return result;
|
||||
}
|
||||
if (getStateForwardedInfo(point, trect, &result, request)) {
|
||||
return result;
|
||||
}
|
||||
|
@ -1847,57 +2023,89 @@ bool Message::getStateFromName(
|
|||
QPoint point,
|
||||
QRect &trect,
|
||||
not_null<TextState*> outResult) const {
|
||||
const auto item = message();
|
||||
if (displayFromName()) {
|
||||
const auto replyWidth = [&] {
|
||||
if (isUnderCursor() && displayFastReply()) {
|
||||
return st::msgFont->width(FastReplyText());
|
||||
if (!displayFromName()) {
|
||||
return false;
|
||||
}
|
||||
const auto replyWidth = [&] {
|
||||
if (isUnderCursor() && displayFastReply()) {
|
||||
return st::msgFont->width(FastReplyText());
|
||||
}
|
||||
return 0;
|
||||
}();
|
||||
if (replyWidth
|
||||
&& point.x() >= trect.left() + trect.width() - replyWidth
|
||||
&& point.x() < trect.left() + trect.width() + st::msgPadding.right()
|
||||
&& point.y() >= trect.top() - st::msgPadding.top()
|
||||
&& point.y() < trect.top() + st::msgServiceFont->height) {
|
||||
outResult->link = fastReplyLink();
|
||||
return true;
|
||||
}
|
||||
if (point.y() >= trect.top() && point.y() < trect.top() + st::msgNameFont->height) {
|
||||
auto availableLeft = trect.left();
|
||||
auto availableWidth = trect.width();
|
||||
if (replyWidth) {
|
||||
availableWidth -= st::msgPadding.right() + replyWidth;
|
||||
}
|
||||
const auto item = message();
|
||||
const auto from = item->displayFrom();
|
||||
const auto nameText = [&]() -> const Ui::Text::String * {
|
||||
if (from) {
|
||||
validateFromNameText(from);
|
||||
return &_fromName;
|
||||
} else if (const auto info = item->hiddenSenderInfo()) {
|
||||
return &info->nameText();
|
||||
} else {
|
||||
Unexpected("Corrupt forwarded information in message.");
|
||||
}
|
||||
return 0;
|
||||
}();
|
||||
if (replyWidth
|
||||
&& point.x() >= trect.left() + trect.width() - replyWidth
|
||||
&& point.x() < trect.left() + trect.width() + st::msgPadding.right()
|
||||
&& point.y() >= trect.top() - st::msgPadding.top()
|
||||
&& point.y() < trect.top() + st::msgServiceFont->height) {
|
||||
outResult->link = fastReplyLink();
|
||||
if (point.x() >= availableLeft
|
||||
&& point.x() < availableLeft + availableWidth
|
||||
&& point.x() < availableLeft + nameText->maxWidth()) {
|
||||
outResult->link = fromLink();
|
||||
return true;
|
||||
}
|
||||
if (point.y() >= trect.top() && point.y() < trect.top() + st::msgNameFont->height) {
|
||||
auto availableLeft = trect.left();
|
||||
auto availableWidth = trect.width();
|
||||
if (replyWidth) {
|
||||
availableWidth -= st::msgPadding.right() + replyWidth;
|
||||
}
|
||||
const auto from = item->displayFrom();
|
||||
const auto nameText = [&]() -> const Ui::Text::String * {
|
||||
if (from) {
|
||||
validateFromNameText(from);
|
||||
return &_fromName;
|
||||
} else if (const auto info = item->hiddenSenderInfo()) {
|
||||
return &info->nameText();
|
||||
} else {
|
||||
Unexpected("Corrupt forwarded information in message.");
|
||||
}
|
||||
}();
|
||||
if (point.x() >= availableLeft
|
||||
&& point.x() < availableLeft + availableWidth
|
||||
&& point.x() < availableLeft + nameText->maxWidth()) {
|
||||
outResult->link = fromLink();
|
||||
return true;
|
||||
}
|
||||
auto via = item->Get<HistoryMessageVia>();
|
||||
if (via
|
||||
&& !displayForwardedFrom()
|
||||
&& point.x() >= availableLeft + nameText->maxWidth() + st::msgServiceFont->spacew
|
||||
&& point.x() < availableLeft + availableWidth
|
||||
&& point.x() < availableLeft + nameText->maxWidth() + st::msgServiceFont->spacew + via->width) {
|
||||
outResult->link = via->link;
|
||||
return true;
|
||||
}
|
||||
auto via = item->Get<HistoryMessageVia>();
|
||||
if (via
|
||||
&& !displayForwardedFrom()
|
||||
&& point.x() >= availableLeft + nameText->maxWidth() + st::msgServiceFont->spacew
|
||||
&& point.x() < availableLeft + availableWidth
|
||||
&& point.x() < availableLeft + nameText->maxWidth() + st::msgServiceFont->spacew + via->width) {
|
||||
outResult->link = via->link;
|
||||
return true;
|
||||
}
|
||||
trect.setTop(trect.top() + st::msgNameFont->height);
|
||||
}
|
||||
trect.setTop(trect.top() + st::msgNameFont->height);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Message::getStateTopicButton(
|
||||
QPoint point,
|
||||
QRect &trect,
|
||||
not_null<TextState*> outResult) const {
|
||||
if (!displayTopicButton()) {
|
||||
return false;
|
||||
}
|
||||
trect.setTop(trect.top() + st::topicButtonSkip);
|
||||
const auto padding = st::topicButtonPadding;
|
||||
const auto availableWidth = trect.width();
|
||||
const auto height = padding.top()
|
||||
+ st::msgNameFont->height
|
||||
+ padding.bottom();
|
||||
const auto width = std::max(
|
||||
std::min(
|
||||
availableWidth,
|
||||
(padding.left()
|
||||
+ _topicButton->name.maxWidth()
|
||||
+ st::topicButtonArrowSkip
|
||||
+ padding.right())),
|
||||
height);
|
||||
const auto rect = QRect(trect.x(), trect.y(), width, height);
|
||||
if (rect.contains(point)) {
|
||||
outResult->link = _topicButton->link;
|
||||
_topicButton->lastPoint = point - rect.topLeft();
|
||||
return true;
|
||||
}
|
||||
trect.setY(trect.y() + height + st::topicButtonSkip);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -1906,56 +2114,57 @@ bool Message::getStateForwardedInfo(
|
|||
QRect &trect,
|
||||
not_null<TextState*> outResult,
|
||||
StateRequest request) const {
|
||||
if (displayForwardedFrom()) {
|
||||
const auto item = message();
|
||||
const auto forwarded = item->Get<HistoryMessageForwarded>();
|
||||
const auto skip1 = forwarded->psaType.isEmpty()
|
||||
? 0
|
||||
: st::historyPsaIconSkip1;
|
||||
const auto skip2 = forwarded->psaType.isEmpty()
|
||||
? 0
|
||||
: st::historyPsaIconSkip2;
|
||||
const auto fits = (forwarded->text.maxWidth() <= (trect.width() - skip1));
|
||||
const auto fwdheight = (fits ? 1 : 2) * st::semiboldFont->height;
|
||||
if (point.y() >= trect.top() && point.y() < trect.top() + fwdheight) {
|
||||
if (skip1) {
|
||||
const auto &icon = st::historyPsaIconIn;
|
||||
const auto position = fits
|
||||
? st::historyPsaIconPosition1
|
||||
: st::historyPsaIconPosition2;
|
||||
const auto iconRect = QRect(
|
||||
trect.x() + trect.width() - position.x() - icon.width(),
|
||||
trect.y() + position.y(),
|
||||
icon.width(),
|
||||
icon.height());
|
||||
if (iconRect.contains(point)) {
|
||||
if (const auto link = psaTooltipLink()) {
|
||||
outResult->link = link;
|
||||
return true;
|
||||
}
|
||||
if (!displayForwardedFrom()) {
|
||||
return false;
|
||||
}
|
||||
const auto item = message();
|
||||
const auto forwarded = item->Get<HistoryMessageForwarded>();
|
||||
const auto skip1 = forwarded->psaType.isEmpty()
|
||||
? 0
|
||||
: st::historyPsaIconSkip1;
|
||||
const auto skip2 = forwarded->psaType.isEmpty()
|
||||
? 0
|
||||
: st::historyPsaIconSkip2;
|
||||
const auto fits = (forwarded->text.maxWidth() <= (trect.width() - skip1));
|
||||
const auto fwdheight = (fits ? 1 : 2) * st::semiboldFont->height;
|
||||
if (point.y() >= trect.top() && point.y() < trect.top() + fwdheight) {
|
||||
if (skip1) {
|
||||
const auto &icon = st::historyPsaIconIn;
|
||||
const auto position = fits
|
||||
? st::historyPsaIconPosition1
|
||||
: st::historyPsaIconPosition2;
|
||||
const auto iconRect = QRect(
|
||||
trect.x() + trect.width() - position.x() - icon.width(),
|
||||
trect.y() + position.y(),
|
||||
icon.width(),
|
||||
icon.height());
|
||||
if (iconRect.contains(point)) {
|
||||
if (const auto link = psaTooltipLink()) {
|
||||
outResult->link = link;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
const auto useWidth = trect.width() - (fits ? skip1 : skip2);
|
||||
const auto breakEverywhere = (forwarded->text.countHeight(useWidth) > 2 * st::semiboldFont->height);
|
||||
auto textRequest = request.forText();
|
||||
if (breakEverywhere) {
|
||||
textRequest.flags |= Ui::Text::StateRequest::Flag::BreakEverywhere;
|
||||
}
|
||||
*outResult = TextState(item, forwarded->text.getState(
|
||||
point - trect.topLeft(),
|
||||
useWidth,
|
||||
textRequest));
|
||||
outResult->symbol = 0;
|
||||
outResult->afterSymbol = false;
|
||||
if (breakEverywhere) {
|
||||
outResult->cursor = CursorState::Forwarded;
|
||||
} else {
|
||||
outResult->cursor = CursorState::None;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
trect.setTop(trect.top() + fwdheight);
|
||||
const auto useWidth = trect.width() - (fits ? skip1 : skip2);
|
||||
const auto breakEverywhere = (forwarded->text.countHeight(useWidth) > 2 * st::semiboldFont->height);
|
||||
auto textRequest = request.forText();
|
||||
if (breakEverywhere) {
|
||||
textRequest.flags |= Ui::Text::StateRequest::Flag::BreakEverywhere;
|
||||
}
|
||||
*outResult = TextState(item, forwarded->text.getState(
|
||||
point - trect.topLeft(),
|
||||
useWidth,
|
||||
textRequest));
|
||||
outResult->symbol = 0;
|
||||
outResult->afterSymbol = false;
|
||||
if (breakEverywhere) {
|
||||
outResult->cursor = CursorState::Forwarded;
|
||||
} else {
|
||||
outResult->cursor = CursorState::None;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
trect.setTop(trect.top() + fwdheight);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -2076,6 +2285,14 @@ void Message::updatePressed(QPoint point) {
|
|||
if (displayFromName()) {
|
||||
trect.setTop(trect.top() + st::msgNameFont->height);
|
||||
}
|
||||
if (displayTopicButton()) {
|
||||
trect.setTop(trect.top()
|
||||
+ st::topicButtonSkip
|
||||
+ st::topicButtonPadding.top()
|
||||
+ st::msgNameFont->height
|
||||
+ st::topicButtonPadding.bottom()
|
||||
+ st::topicButtonSkip);
|
||||
}
|
||||
if (displayForwardedFrom()) {
|
||||
auto forwarded = item->Get<HistoryMessageForwarded>();
|
||||
auto fwdheight = ((forwarded->text.maxWidth() > trect.width()) ? 2 : 1) * st::semiboldFont->height;
|
||||
|
@ -2652,6 +2869,10 @@ bool Message::hasBubble() const {
|
|||
return drawBubble();
|
||||
}
|
||||
|
||||
bool Message::displayTopicButton() const {
|
||||
return _topicButton != nullptr;
|
||||
}
|
||||
|
||||
bool Message::unwrapped() const {
|
||||
const auto item = message();
|
||||
if (isHidden()) {
|
||||
|
@ -2946,6 +3167,7 @@ void Message::updateMediaInBubbleState() {
|
|||
auto mediaHasSomethingAbove = false;
|
||||
auto getMediaHasSomethingAbove = [&] {
|
||||
return displayFromName()
|
||||
|| displayTopicButton()
|
||||
|| displayForwardedFrom()
|
||||
|| displayedReply()
|
||||
|| item->Has<HistoryMessageVia>();
|
||||
|
@ -3064,6 +3286,13 @@ QRect Message::innerGeometry() const {
|
|||
// See paintFromName().
|
||||
result.translate(0, st::msgNameFont->height);
|
||||
}
|
||||
if (displayTopicButton()) {
|
||||
result.translate(0, st::topicButtonSkip
|
||||
+ st::topicButtonPadding.top()
|
||||
+ st::msgNameFont->height
|
||||
+ st::topicButtonPadding.bottom()
|
||||
+ st::topicButtonSkip);
|
||||
}
|
||||
// Skip displayForwardedFrom() until there are no animations for it.
|
||||
if (displayedReply()) {
|
||||
// See paintReplyInfo().
|
||||
|
@ -3284,6 +3513,14 @@ int Message::resizeContentGetHeight(int newWidth) {
|
|||
newHeight += st::msgNameFont->height;
|
||||
}
|
||||
|
||||
if (displayTopicButton()) {
|
||||
newHeight += st::topicButtonSkip
|
||||
+ st::topicButtonPadding.top()
|
||||
+ st::msgNameFont->height
|
||||
+ st::topicButtonPadding.bottom()
|
||||
+ st::topicButtonSkip;
|
||||
}
|
||||
|
||||
if (displayForwardedFrom()) {
|
||||
const auto forwarded = item->Get<HistoryMessageForwarded>();
|
||||
const auto skip1 = forwarded->psaType.isEmpty()
|
||||
|
|
|
@ -123,6 +123,7 @@ public:
|
|||
bool hasOutLayout() const override;
|
||||
bool drawBubble() const override;
|
||||
bool hasBubble() const override;
|
||||
bool displayTopicButton() const override;
|
||||
bool unwrapped() const override;
|
||||
int minWidthForMedia() const override;
|
||||
bool hasFastReply() const override;
|
||||
|
@ -167,6 +168,7 @@ protected:
|
|||
private:
|
||||
struct CommentsButton;
|
||||
struct FromNameStatus;
|
||||
struct TopicButton;
|
||||
|
||||
void initLogEntryOriginal();
|
||||
void initPsa();
|
||||
|
@ -180,7 +182,10 @@ private:
|
|||
TextSelection selection) const;
|
||||
|
||||
void toggleCommentsButtonRipple(bool pressed);
|
||||
void createCommentsRipple();
|
||||
void createCommentsButtonRipple();
|
||||
|
||||
void toggleTopicButtonRipple(bool pressed);
|
||||
void createTopicButtonRipple();
|
||||
|
||||
void paintCommentsButton(
|
||||
Painter &p,
|
||||
|
@ -190,6 +195,10 @@ private:
|
|||
Painter &p,
|
||||
QRect &trect,
|
||||
const PaintContext &context) const;
|
||||
void paintTopicButton(
|
||||
Painter &p,
|
||||
QRect &trect,
|
||||
const PaintContext &context) const;
|
||||
void paintForwardedInfo(
|
||||
Painter &p,
|
||||
QRect &trect,
|
||||
|
@ -217,6 +226,10 @@ private:
|
|||
QPoint point,
|
||||
QRect &trect,
|
||||
not_null<TextState*> outResult) const;
|
||||
bool getStateTopicButton(
|
||||
QPoint point,
|
||||
QRect &trect,
|
||||
not_null<TextState*> outResult) const;
|
||||
bool getStateForwardedInfo(
|
||||
QPoint point,
|
||||
QRect &trect,
|
||||
|
@ -257,6 +270,7 @@ private:
|
|||
[[nodiscard]] bool displayGoToOriginal() const;
|
||||
[[nodiscard]] ClickHandlerPtr fastReplyLink() const;
|
||||
|
||||
void refreshTopicButton();
|
||||
void refreshInfoSkipBlock();
|
||||
[[nodiscard]] int plainMaxWidth() const;
|
||||
[[nodiscard]] int monospaceMaxWidth() const;
|
||||
|
@ -279,6 +293,7 @@ private:
|
|||
mutable ClickHandlerPtr _fastReplyLink;
|
||||
mutable std::unique_ptr<ViewButton> _viewButton;
|
||||
std::unique_ptr<Reactions::InlineList> _reactions;
|
||||
std::unique_ptr<TopicButton> _topicButton;
|
||||
mutable std::unique_ptr<CommentsButton> _comments;
|
||||
|
||||
mutable Ui::Text::String _fromName;
|
||||
|
|
|
@ -703,7 +703,7 @@ void TopBarWidget::backClicked() {
|
|||
_controller->closeFolder();
|
||||
} else if (_activeChat.section == Section::ChatsList
|
||||
&& _activeChat.key.history()
|
||||
&& _activeChat.key.history()->peer->isForum()) {
|
||||
&& _activeChat.key.history()->isForum()) {
|
||||
_controller->closeForum();
|
||||
} else {
|
||||
_controller->showBackFromStack();
|
||||
|
|
|
@ -430,7 +430,8 @@ bool ExtendedPreview::needsBubble() const {
|
|||
|| item->viaBot()
|
||||
|| _parent->displayedReply()
|
||||
|| _parent->displayForwardedFrom()
|
||||
|| _parent->displayFromName());
|
||||
|| _parent->displayFromName()
|
||||
|| _parent->displayTopicButton());
|
||||
}
|
||||
|
||||
QPoint ExtendedPreview::resolveCustomInfoRightBottom() const {
|
||||
|
|
|
@ -1308,7 +1308,8 @@ bool Gif::needsBubble() const {
|
|||
|| item->viaBot()
|
||||
|| _parent->displayedReply()
|
||||
|| _parent->displayForwardedFrom()
|
||||
|| _parent->displayFromName();
|
||||
|| _parent->displayFromName()
|
||||
|| _parent->displayTopicButton();
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -377,7 +377,8 @@ bool Location::needsBubble() const {
|
|||
|| item->viaBot()
|
||||
|| _parent->displayedReply()
|
||||
|| _parent->displayForwardedFrom()
|
||||
|| _parent->displayFromName();
|
||||
|| _parent->displayFromName()
|
||||
|| _parent->displayTopicButton();
|
||||
}
|
||||
|
||||
QPoint Location::resolveCustomInfoRightBottom() const {
|
||||
|
|
|
@ -775,6 +775,7 @@ bool GroupedMedia::computeNeedBubble() const {
|
|||
|| _parent->displayedReply()
|
||||
|| _parent->displayForwardedFrom()
|
||||
|| _parent->displayFromName()
|
||||
|| _parent->displayTopicButton()
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -412,7 +412,7 @@ void Photo::paintUserpicFrame(
|
|||
auto request = ::Media::Streaming::FrameRequest();
|
||||
request.outer = size * cIntRetinaFactor();
|
||||
request.resize = size * cIntRetinaFactor();
|
||||
const auto forum = _parent->data()->history()->peer->isForum();
|
||||
const auto forum = _parent->data()->history()->isForum();
|
||||
if (forum) {
|
||||
request.rounding = Images::CornersMaskRef(
|
||||
Images::CornersMask(ImageRoundRadius::Large));
|
||||
|
@ -439,7 +439,7 @@ void Photo::paintUserpicFrame(
|
|||
return;
|
||||
}
|
||||
const auto pix = [&] {
|
||||
const auto forum = _parent->data()->history()->peer->isForum();
|
||||
const auto forum = _parent->data()->history()->isForum();
|
||||
const auto args = Images::PrepareArgs{
|
||||
.options = (forum
|
||||
? Images::Option::RoundLarge
|
||||
|
@ -885,7 +885,8 @@ bool Photo::needsBubble() const {
|
|||
|| item->viaBot()
|
||||
|| _parent->displayedReply()
|
||||
|| _parent->displayForwardedFrom()
|
||||
|| _parent->displayFromName());
|
||||
|| _parent->displayFromName()
|
||||
|| _parent->displayTopicButton());
|
||||
}
|
||||
|
||||
QPoint Photo::resolveCustomInfoRightBottom() const {
|
||||
|
|
|
@ -261,7 +261,7 @@ void Uploader::sendProgressUpdate(
|
|||
if (history->peer->isMegagroup()) {
|
||||
manager.update(history, replyTo, type, progress);
|
||||
}
|
||||
} else if (history->peer->isForum()) {
|
||||
} else if (history->isForum()) {
|
||||
manager.update(history, item->topicRootId(), type, progress);
|
||||
}
|
||||
_api->session().data().requestItemRepaint(item);
|
||||
|
|
|
@ -649,6 +649,12 @@ historyPinnedBotButton: RoundButton(defaultActiveButton) {
|
|||
}
|
||||
historyPinnedBotButtonMaxWidth: 150px;
|
||||
|
||||
topicButtonSkip: 3px;
|
||||
topicButtonPadding: margins(6px, 3px, 8px, 3px);
|
||||
topicButtonArrowSkip: 8px;
|
||||
topicButtonArrowPosition: point(3px, 3px);
|
||||
topicButtonArrow: icon{{ "dialogs/dialogs_topic_arrow", historyReplyIconFg }};
|
||||
|
||||
msgBotKbDuration: 200;
|
||||
msgBotKbFont: semiboldFont;
|
||||
msgBotKbIconPadding: 4px;
|
||||
|
|
Loading…
Add table
Reference in a new issue