Show comments unread status.

This commit is contained in:
John Preston 2020-09-15 11:39:39 +03:00
parent 040f29abe6
commit 59abe95754
9 changed files with 155 additions and 63 deletions

View file

@ -169,7 +169,9 @@ bool RepliesList::buildFromData(not_null<Viewer*> viewer) {
if (viewer->around != ShowAtUnreadMsgId) {
return viewer->around;
} else if (const auto item = lookupRoot()) {
return item->repliesReadTill();
if (const auto original = item->lookupDiscussionPostOriginal()) {
return original->commentsReadTill();
}
}
return viewer->around;
}();
@ -439,9 +441,9 @@ bool RepliesList::processMessagesIsEmpty(const MTPmessages_Messages &result) {
return true;
}
const auto id = IdFromMessage(list.front());
const auto maxId = IdFromMessage(list.front());
const auto wasSize = int(_list.size());
const auto toFront = (wasSize > 0) && (id > _list.front());
const auto toFront = (wasSize > 0) && (maxId > _list.front());
const auto clientFlags = MTPDmessage_ClientFlags();
const auto type = NewMessageType::Existing;
auto refreshed = std::vector<MsgId>();
@ -488,6 +490,17 @@ bool RepliesList::processMessagesIsEmpty(const MTPmessages_Messages &result) {
_skippedBefore = checkedCount - *_skippedAfter - nowSize;
}
_fullCount = checkedCount;
if (const auto item = lookupRoot()) {
if (const auto original = item->lookupDiscussionPostOriginal()) {
if (_skippedAfter == 0) {
original->setCommentsMaxId(_list.front());
} else {
original->setCommentsPossibleMaxId(maxId);
}
}
}
return false;
}

View file

@ -256,6 +256,21 @@ bool HistoryItem::isDiscussionPost() const {
return (discussionPostOriginalSender() != nullptr);
}
HistoryItem *HistoryItem::lookupDiscussionPostOriginal() const {
if (!history()->peer->isMegagroup()) {
return nullptr;
}
const auto forwarded = Get<HistoryMessageForwarded>();
if (!forwarded
|| !forwarded->savedFromPeer
|| !forwarded->savedFromMsgId) {
return nullptr;
}
return _history->owner().message(
forwarded->savedFromPeer->asChannel(),
forwarded->savedFromMsgId);
}
PeerData *HistoryItem::displayFrom() const {
if (const auto sender = discussionPostOriginalSender()) {
return sender;

View file

@ -206,6 +206,18 @@ public:
}
virtual void setCommentsItemId(FullMsgId id) {
}
[[nodiscard]] virtual MsgId commentsReadTill() const {
return MsgId(0);
}
virtual void setCommentsReadTill(MsgId readTillId) {
}
virtual void setCommentsMaxId(MsgId maxId) {
}
virtual void setCommentsPossibleMaxId(MsgId possibleMaxId) {
}
[[nodiscard]] virtual bool areCommentsUnread() const {
return false;
}
[[nodiscard]] virtual bool needCheck() const;
@ -267,11 +279,6 @@ public:
}
virtual void changeRepliesCount(int delta, PeerId replier) {
}
virtual void setRepliesReadTill(MsgId readTillId) {
}
[[nodiscard]] virtual MsgId repliesReadTill() const {
return MsgId(0);
}
virtual void setReplyToTop(MsgId replyToTop) {
}
virtual void setRealId(MsgId newId);
@ -356,6 +363,7 @@ public:
[[nodiscard]] ChannelData *discussionPostOriginalSender() const;
[[nodiscard]] bool isDiscussionPost() const;
[[nodiscard]] HistoryItem *lookupDiscussionPostOriginal() const;
[[nodiscard]] PeerData *displayFrom() const;
[[nodiscard]] virtual std::unique_ptr<HistoryView::Element> createView(

View file

@ -46,7 +46,8 @@ struct HistoryMessageViews : public RuntimeComponent<HistoryMessageViews, Histor
Part replies;
ChannelId commentsChannelId = 0;
MsgId commentsRootId = 0;
MsgId repliesReadTillId = 0;
MsgId commentsReadTillId = 0;
MsgId commentsMaxId = 0;
};
struct HistoryMessageSigned : public RuntimeComponent<HistoryMessageSigned, HistoryItem> {

View file

@ -814,6 +814,58 @@ void HistoryMessage::setCommentsItemId(FullMsgId id) {
}
}
MsgId HistoryMessage::commentsReadTill() const {
if (const auto views = Get<HistoryMessageViews>()) {
return views->commentsReadTillId;
}
return 0;
}
void HistoryMessage::setCommentsReadTill(MsgId readTillId) {
if (const auto views = Get<HistoryMessageViews>()) {
const auto newReadTillId = std::max(readTillId, 1);
if (newReadTillId > views->commentsReadTillId) {
const auto wasUnread = areCommentsUnread();
views->commentsReadTillId = newReadTillId;
if (wasUnread && !areCommentsUnread()) {
history()->owner().requestItemRepaint(this);
}
}
}
}
void HistoryMessage::setCommentsMaxId(MsgId maxId) {
if (const auto views = Get<HistoryMessageViews>()) {
if (views->commentsMaxId != maxId) {
const auto wasUnread = areCommentsUnread();
views->commentsMaxId = maxId;
if (wasUnread != areCommentsUnread()) {
history()->owner().requestItemRepaint(this);
}
}
}
}
void HistoryMessage::setCommentsPossibleMaxId(MsgId possibleMaxId) {
if (const auto views = Get<HistoryMessageViews>()) {
if (views->commentsMaxId < possibleMaxId) {
const auto wasUnread = areCommentsUnread();
views->commentsMaxId = possibleMaxId;
if (!wasUnread && areCommentsUnread()) {
history()->owner().requestItemRepaint(this);
}
}
}
}
bool HistoryMessage::areCommentsUnread() const {
if (const auto views = Get<HistoryMessageViews>()) {
return (views->commentsReadTillId > 1)
&& (views->commentsMaxId > views->commentsReadTillId);
}
return false;
}
bool HistoryMessage::updateDependencyItem() {
if (const auto reply = Get<HistoryMessageReply>()) {
const auto documentId = reply->replyToDocumentId;
@ -1531,6 +1583,17 @@ void HistoryMessage::setReplies(const MTPMessageReplies &data) {
views->recentRepliers = repliers;
}
views->commentsChannelId = channelId;
const auto wasUnread = areCommentsUnread();
if (const auto till = data.vread_max_id()) {
views->commentsReadTillId = std::max(
{ views->commentsReadTillId, till->v, 1 });
}
if (const auto maxId = data.vmax_id()) {
views->commentsMaxId = maxId->v;
}
if (wasUnread != areCommentsUnread()) {
history()->owner().requestItemRepaint(this);
}
refreshRepliesText(views, channelChanged);
});
}
@ -1585,22 +1648,6 @@ void HistoryMessage::changeRepliesCount(int delta, PeerId replier) {
refreshRepliesText(views);
}
void HistoryMessage::setRepliesReadTill(MsgId readTillId) {
auto views = Get<HistoryMessageViews>();
if (!views) {
AddComponents(HistoryMessageViews::Bit());
views = Get<HistoryMessageViews>();
}
views->repliesReadTillId = std::max(readTillId, 1);
}
MsgId HistoryMessage::repliesReadTill() const {
if (const auto views = Get<HistoryMessageViews>()) {
return views->repliesReadTillId;
}
return 0;
}
void HistoryMessage::setReplyToTop(MsgId replyToTop) {
const auto reply = Get<HistoryMessageReply>();
if (!reply
@ -1662,15 +1709,8 @@ void HistoryMessage::changeReplyToTopCounter(
}
}
changeFor(top);
if (const auto sender = top->discussionPostOriginalSender()) {
if (const auto forwarded = top->Get<HistoryMessageForwarded>()) {
const auto id = FullMsgId(
sender->bareId(),
forwarded->savedFromMsgId);
if (const auto original = history()->owner().message(id)) {
changeFor(original);
}
}
if (const auto original = top->lookupDiscussionPostOriginal()) {
changeFor(original);
}
}

View file

@ -136,8 +136,6 @@ public:
void setForwardsCount(int count) override;
void setReplies(const MTPMessageReplies &data) override;
void changeRepliesCount(int delta, PeerId replier) override;
void setRepliesReadTill(MsgId readTillId) override;
MsgId repliesReadTill() const override;
void setReplyToTop(MsgId replyToTop) override;
void setRealId(MsgId newId) override;
void incrementReplyToTopCounter() override;
@ -173,6 +171,11 @@ public:
[[nodiscard]] bool externalReply() const override;
[[nodiscard]] FullMsgId commentsItemId() const override;
void setCommentsItemId(FullMsgId id) override;
[[nodiscard]] MsgId commentsReadTill() const override;
void setCommentsReadTill(MsgId readTillId) override;
void setCommentsMaxId(MsgId maxId) override;
void setCommentsPossibleMaxId(MsgId possibleMaxId) override;
[[nodiscard]] bool areCommentsUnread() const override;
bool updateDependencyItem() override;
[[nodiscard]] MsgId dependencyMsgId() const override {
return replyToId();

View file

@ -373,7 +373,9 @@ QSize Message::performCountOptimalSize() {
+ st::historyCommentsSkipRight
+ st::historyCommentsSkipText
+ st::historyCommentsOpenOutSelected.width()
+ st::historyCommentsSkipRight;
+ st::historyCommentsSkipRight
+ st::mediaUnreadSkip
+ st::mediaUnreadSize;
accumulate_max(maxWidth, added + views->replies.textWidth);
} else if (item->externalReply()) {
const auto added = st::historyCommentsIn.width()
@ -718,12 +720,23 @@ void Message::paintCommentsButton(
p.setPen(outbg ? (selected ? st::msgFileThumbLinkOutFgSelected : st::msgFileThumbLinkOutFg) : (selected ? st::msgFileThumbLinkInFgSelected : st::msgFileThumbLinkInFg));
p.setFont(st::semiboldFont);
const auto textTop = top + (st::historyCommentsButtonHeight - st::semiboldFont->height) / 2;
p.drawTextLeft(
left,
top + (st::historyCommentsButtonHeight - st::semiboldFont->height) / 2,
textTop,
width,
views ? views->replies.text : tr::lng_replies_view_original(tr::now),
views ? views->replies.textWidth : -1);
if (views && data()->areCommentsUnread()) {
p.setPen(Qt::NoPen);
p.setBrush(outbg ? (selected ? st::msgFileOutBgSelected : st::msgFileOutBg) : (selected ? st::msgFileInBgSelected : st::msgFileInBg));
{
PainterHighQualityEnabler hq(p);
p.drawEllipse(style::rtlrect(left + views->replies.textWidth + st::mediaUnreadSkip, textTop + st::mediaUnreadTop, st::mediaUnreadSize, st::mediaUnreadSize, width));
}
}
}
void Message::paintFromName(

View file

@ -84,11 +84,13 @@ bool CanSendFiles(not_null<const QMimeData*> data) {
RepliesMemento::RepliesMemento(not_null<HistoryItem*> commentsItem)
: RepliesMemento(commentsItem->history(), commentsItem->id) {
if (commentsItem->repliesReadTill() == MsgId(1)) {
_list.setAroundPosition(Data::MinMessagePosition);
_list.setScrollTopState(ListMemento::ScrollTopState{
Data::MinMessagePosition
});
if (const auto original = commentsItem->lookupDiscussionPostOriginal()) {
if (original->commentsReadTill() == MsgId(1)) {
_list.setAroundPosition(Data::MinMessagePosition);
_list.setScrollTopState(ListMemento::ScrollTopState{
Data::MinMessagePosition
});
}
}
}
@ -215,7 +217,7 @@ RepliesWidget::~RepliesWidget() {
}
void RepliesWidget::sendReadTillRequest() {
if (!_commentsRoot || !_root) {
if (!_commentsRoot) {
return;
}
if (_readRequestTimer.isActive()) {
@ -226,9 +228,8 @@ void RepliesWidget::sendReadTillRequest() {
_readRequestId = api->request(MTPmessages_ReadDiscussion(
_commentsRoot->history()->peer->input,
MTP_int(_commentsRoot->id),
MTP_int(_root->repliesReadTill())
MTP_int(_commentsRoot->commentsReadTill())
)).done([=](const MTPBool &) {
}).send();
}
@ -307,14 +308,9 @@ HistoryItem *RepliesWidget::lookupRoot() const {
}
HistoryItem *RepliesWidget::lookupCommentsRoot() const {
if (!computeAreComments()) {
return nullptr;
}
const auto forwarded = _root->Get<HistoryMessageForwarded>();
Assert(forwarded != nullptr);
return _history->owner().message(
forwarded->savedFromPeer->asChannel(),
forwarded->savedFromMsgId);
return _root
? _root->lookupDiscussionPostOriginal()
: nullptr;
}
bool RepliesWidget::computeAreComments() const {
@ -1446,12 +1442,12 @@ void RepliesWidget::listSelectionChanged(SelectedItems &&items) {
}
void RepliesWidget::readTill(MsgId tillId) {
if (!_root) {
if (!_commentsRoot) {
return;
}
const auto now = _root->repliesReadTill();
const auto now = _commentsRoot->commentsReadTill();
if (now < tillId) {
_root->setRepliesReadTill(tillId);
_commentsRoot->setCommentsReadTill(tillId);
if (!_readRequestTimer.isActive()) {
_readRequestTimer.callOnce(kReadRequestTimeout);
}
@ -1470,10 +1466,10 @@ void RepliesWidget::listVisibleItemsChanged(HistoryItemsList &&items) {
std::optional<int> RepliesWidget::listUnreadBarView(
const std::vector<not_null<Element*>> &elements) {
if (!_root) {
if (!_commentsRoot) {
return std::nullopt;
}
const auto till = _root->repliesReadTill();
const auto till = _commentsRoot->commentsReadTill();
if (till < 2) {
return std::nullopt;
}
@ -1481,7 +1477,7 @@ std::optional<int> RepliesWidget::listUnreadBarView(
const auto item = elements[i]->data();
if (item->id > till) {
if (item->out()) {
_root->setRepliesReadTill(item->id);
_commentsRoot->setCommentsReadTill(item->id);
_readRequestTimer.callOnce(kReadRequestTimeout);
} else {
return i;

View file

@ -147,9 +147,12 @@ void SessionNavigation::showRepliesForMessage(
const auto post = _session->data().message(channelId, rootId);
if (post) {
post->setCommentsItemId(item->fullId());
}
if (const auto readTill = data.vread_max_id()) {
item->setRepliesReadTill(readTill->v);
if (const auto maxId = data.vmax_id()) {
post->setCommentsMaxId(maxId->v);
}
if (const auto readTill = data.vread_max_id()) {
post->setCommentsReadTill(readTill->v);
}
}
showSection(
HistoryView::RepliesMemento(item));