mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-07-27 07:52:57 +02:00
Correctly mark monoforum chats as read.
This commit is contained in:
parent
7f7b764f7b
commit
f4582ddf36
9 changed files with 135 additions and 8 deletions
|
@ -711,6 +711,7 @@ void Histories::sendReadRequest(not_null<History*> history, State &state) {
|
|||
} else {
|
||||
Assert(!state->sentReadTill || state->sentReadTill > tillId);
|
||||
}
|
||||
history->validateMonoforumUnread(tillId);
|
||||
sendReadRequests();
|
||||
finish();
|
||||
};
|
||||
|
|
|
@ -521,6 +521,27 @@ auto SavedMessages::recentSublists() const
|
|||
return _lastSublists;
|
||||
}
|
||||
|
||||
void SavedMessages::markUnreadCountsUnknown(MsgId readTillId) {
|
||||
for (const auto &[peer, sublist] : _sublists) {
|
||||
if (sublist->unreadCountCurrent() > 0) {
|
||||
sublist->setInboxReadTill(readTillId, std::nullopt);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SavedMessages::updateUnreadCounts(
|
||||
MsgId readTillId,
|
||||
const base::flat_map<not_null<SavedSublist*>, int> &counts) {
|
||||
for (const auto &[peer, sublist] : _sublists) {
|
||||
const auto raw = sublist.get();
|
||||
const auto i = counts.find(raw);
|
||||
const auto count = (i != end(counts)) ? i->second : 0;
|
||||
if (raw->unreadCountCurrent() != count) {
|
||||
raw->setInboxReadTill(readTillId, count);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
rpl::producer<> SavedMessages::destroyed() const {
|
||||
if (!_parentChat) {
|
||||
return rpl::never<>();
|
||||
|
|
|
@ -70,6 +70,11 @@ public:
|
|||
[[nodiscard]] auto recentSublists() const
|
||||
-> const std::vector<not_null<SavedSublist*>> &;
|
||||
|
||||
void markUnreadCountsUnknown(MsgId readTillId);
|
||||
void updateUnreadCounts(
|
||||
MsgId readTillId,
|
||||
const base::flat_map<not_null<SavedSublist*>, int> &counts);
|
||||
|
||||
void clear();
|
||||
|
||||
[[nodiscard]] rpl::lifetime &lifetime();
|
||||
|
|
|
@ -7,6 +7,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
*/
|
||||
#include "data/data_saved_sublist.h"
|
||||
|
||||
#include "api/api_unread_things.h"
|
||||
#include "apiwrap.h"
|
||||
#include "core/application.h"
|
||||
#include "data/data_changes.h"
|
||||
|
@ -61,7 +62,7 @@ SavedSublist::~SavedSublist() {
|
|||
if (_readRequestTimer.isActive()) {
|
||||
sendReadTillRequest();
|
||||
}
|
||||
// session().api().unreadThings().cancelRequests(this);
|
||||
session().api().unreadThings().cancelRequests(this);
|
||||
}
|
||||
|
||||
bool SavedSublist::inMonoforum() const {
|
||||
|
@ -444,6 +445,9 @@ void SavedSublist::setInboxReadTill(
|
|||
&& !_list.empty()
|
||||
&& _inboxReadTillId >= _list.front()) {
|
||||
unreadCount = 0;
|
||||
} else if (_lastServerMessage.value_or(nullptr)
|
||||
&& (*_lastServerMessage)->id <= newReadTillId) {
|
||||
unreadCount = 0;
|
||||
}
|
||||
if (_unreadCount.current() != unreadCount
|
||||
&& (changed || unreadCount.has_value())) {
|
||||
|
@ -646,10 +650,11 @@ void SavedSublist::sendReadTillRequest() {
|
|||
const auto api = &_parent->session().api();
|
||||
api->request(base::take(_readRequestId)).cancel();
|
||||
|
||||
_sentReadTill = computeInboxReadTillFull();
|
||||
_readRequestId = api->request(MTPmessages_ReadSavedHistory(
|
||||
parentChat->input,
|
||||
sublistPeer()->input,
|
||||
MTP_int(computeInboxReadTillFull())
|
||||
MTP_int(_sentReadTill.bare)
|
||||
)).done(crl::guard(this, [=] {
|
||||
_readRequestId = 0;
|
||||
reloadUnreadCountIfNeeded();
|
||||
|
@ -708,6 +713,20 @@ void SavedSublist::applyMonoforumDialog(
|
|||
setInboxReadTill(
|
||||
data.vread_inbox_max_id().v,
|
||||
data.vunread_count().v);
|
||||
if (!unreadCountKnown() && !_readRequestId) {
|
||||
// We got read_inbox_max_id < than our current inboxReadTillId,
|
||||
// we need either to send a read request with this new value,
|
||||
// or to downgrade inboxReadTillId locally.
|
||||
if (_sentReadTill < computeInboxReadTillFull()) {
|
||||
sendReadTillRequest();
|
||||
} else {
|
||||
// Just if nothing else helps.
|
||||
_inboxReadTillId = 0;
|
||||
setInboxReadTill(
|
||||
data.vread_inbox_max_id().v,
|
||||
data.vunread_count().v);
|
||||
}
|
||||
}
|
||||
setOutboxReadTill(data.vread_outbox_max_id().v);
|
||||
unreadReactions().setCount(data.vunread_reactions_count().v);
|
||||
setUnreadMark(data.is_unread_mark());
|
||||
|
|
|
@ -184,6 +184,7 @@ private:
|
|||
|
||||
base::Timer _readRequestTimer;
|
||||
mtpRequestId _readRequestId = 0;
|
||||
MsgId _sentReadTill = 0;
|
||||
|
||||
mtpRequestId _reloadUnreadCountRequestId = 0;
|
||||
|
||||
|
|
|
@ -3108,8 +3108,70 @@ void History::applyDialogTopMessage(MsgId topMessageId) {
|
|||
}
|
||||
}
|
||||
|
||||
void History::tryMarkMonoforumIntervalRead(
|
||||
MsgId wasInboxReadBefore,
|
||||
MsgId nowInboxReadBefore) {
|
||||
if (!amMonoforumAdmin() || (nowInboxReadBefore <= wasInboxReadBefore)) {
|
||||
return;
|
||||
} else if (loadedAtBottom() && nowInboxReadBefore >= minMsgId()) {
|
||||
// Count for each sublist how many messages are still not read.
|
||||
auto counts = base::flat_map<not_null<Data::SavedSublist*>, int>();
|
||||
for (const auto &block : blocks) {
|
||||
for (const auto &message : block->messages) {
|
||||
const auto item = message->data();
|
||||
if (!item->isRegular() || item->id < nowInboxReadBefore) {
|
||||
continue;
|
||||
}
|
||||
if (const auto sublist = item->savedSublist()) {
|
||||
++counts[sublist];
|
||||
}
|
||||
}
|
||||
}
|
||||
if (const auto monoforum = peer->monoforum()) {
|
||||
monoforum->updateUnreadCounts(nowInboxReadBefore - 1, counts);
|
||||
}
|
||||
} else if (minMsgId() <= wasInboxReadBefore
|
||||
&& maxMsgId() >= nowInboxReadBefore) {
|
||||
// Count for each sublist how many messages were read.
|
||||
for (const auto &block : blocks) {
|
||||
for (const auto &message : block->messages) {
|
||||
const auto item = message->data();
|
||||
if (!item->isRegular() || item->id < wasInboxReadBefore) {
|
||||
continue;
|
||||
} else if (item->id >= nowInboxReadBefore) {
|
||||
break;
|
||||
}
|
||||
if (const auto sublist = item->savedSublist()) {
|
||||
const auto unread = sublist->unreadCountCurrent();
|
||||
if (unread > 0) {
|
||||
sublist->setInboxReadTill(item->id, unread - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// We can't invalidate sublist unread counts here, because no read
|
||||
// request was yet sent to the server (so it can't return correct
|
||||
// values yet), we need to do that after we send read request.
|
||||
_flags |= Flag::MonoforumUnreadInvalidatePending;
|
||||
}
|
||||
}
|
||||
|
||||
void History::validateMonoforumUnread(MsgId readTillId) {
|
||||
if (!(_flags & Flag::MonoforumUnreadInvalidatePending)) {
|
||||
return;
|
||||
}
|
||||
_flags &= ~Flag::MonoforumUnreadInvalidatePending;
|
||||
if (!amMonoforumAdmin()) {
|
||||
return;
|
||||
} else if (const auto monoforum = peer->monoforum()) {
|
||||
monoforum->markUnreadCountsUnknown(readTillId);
|
||||
}
|
||||
}
|
||||
|
||||
void History::setInboxReadTill(MsgId upTo) {
|
||||
if (_inboxReadBefore) {
|
||||
tryMarkMonoforumIntervalRead(*_inboxReadBefore, upTo + 1);
|
||||
accumulate_max(*_inboxReadBefore, upTo + 1);
|
||||
} else {
|
||||
_inboxReadBefore = upTo + 1;
|
||||
|
|
|
@ -430,6 +430,10 @@ public:
|
|||
// Interface for Data::Histories.
|
||||
void setInboxReadTill(MsgId upTo);
|
||||
std::optional<int> countStillUnreadLocal(MsgId readTillId) const;
|
||||
void tryMarkMonoforumIntervalRead(
|
||||
MsgId wasInboxReadBefore,
|
||||
MsgId nowInboxReadBefore);
|
||||
void validateMonoforumUnread(MsgId readTillId);
|
||||
|
||||
[[nodiscard]] bool isTopPromoted() const;
|
||||
|
||||
|
@ -466,7 +470,7 @@ public:
|
|||
private:
|
||||
friend class HistoryBlock;
|
||||
|
||||
enum class Flag : uchar {
|
||||
enum class Flag : ushort {
|
||||
HasPendingResizedItems = (1 << 0),
|
||||
PendingAllItemsResize = (1 << 1),
|
||||
IsTopPromoted = (1 << 2),
|
||||
|
@ -475,6 +479,7 @@ private:
|
|||
FakeUnreadWhileOpened = (1 << 5),
|
||||
HasPinnedMessages = (1 << 6),
|
||||
ResolveChatListMessage = (1 << 7),
|
||||
MonoforumUnreadInvalidatePending = (1 << 8),
|
||||
};
|
||||
using Flags = base::flags<Flag>;
|
||||
friend inline constexpr auto is_flag_type(Flag) {
|
||||
|
|
|
@ -3632,10 +3632,11 @@ void HistoryWidget::unreadCountUpdated() {
|
|||
});
|
||||
} else {
|
||||
const auto hideCounter = _history->isForum()
|
||||
|| _history->amMonoforumAdmin()
|
||||
|| !_history->trackUnreadMessages();
|
||||
_cornerButtons.updateJumpDownVisibility(hideCounter
|
||||
? 0
|
||||
: _history->amMonoforumAdmin()
|
||||
? _history->chatListUnreadState().messages
|
||||
: _history->chatListBadgesState().unreadCounter);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -349,7 +349,6 @@ void SubsectionTabs::setupSlider(
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
slider->setSections({
|
||||
.tabs = std::move(sections),
|
||||
.context = Core::TextContext({
|
||||
|
@ -591,11 +590,24 @@ void SubsectionTabs::refreshSlice() {
|
|||
const auto push = [&](not_null<Data::Thread*> thread) {
|
||||
const auto topic = thread->asTopic();
|
||||
const auto sublist = thread->asSublist();
|
||||
const auto badges = [&] {
|
||||
if (!topic && !sublist) {
|
||||
return Dialogs::BadgesState();
|
||||
} else if (thread->chatListUnreadState().known) {
|
||||
return thread->chatListBadgesState();
|
||||
}
|
||||
const auto i = ranges::find(_slice, thread, &Item::thread);
|
||||
if (i != end(_slice)) {
|
||||
// While the unread count is unknown (possibly loading)
|
||||
// we can preserve the old badges state, because it won't
|
||||
// glitch that way when we stop knowing it for a moment.
|
||||
return i->badges;
|
||||
}
|
||||
return thread->chatListBadgesState();
|
||||
}();
|
||||
slice.push_back({
|
||||
.thread = thread,
|
||||
.badges = ((topic || sublist)
|
||||
? thread->chatListBadgesState()
|
||||
: Dialogs::BadgesState()),
|
||||
.badges = badges,
|
||||
.iconId = topic ? topic->iconId() : DocumentId(),
|
||||
.name = thread->chatListName(),
|
||||
});
|
||||
|
|
Loading…
Add table
Reference in a new issue