mirror of
https://github.com/telegramdesktop/tdesktop
synced 2025-01-11 09:19:35 +00:00
Mark [un]read from chats list.
This commit is contained in:
parent
372cf275e0
commit
35c759c6bc
@ -1106,6 +1106,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
"lng_context_view_feed_info" = "View feed info";
|
||||
"lng_context_pin_to_top" = "Pin to top";
|
||||
"lng_context_unpin_from_top" = "Unpin from top";
|
||||
"lng_context_mark_unread" = "Mark as unread";
|
||||
"lng_context_mark_read" = "Mark as read";
|
||||
|
||||
"lng_context_promote_admin" = "Promote to admin";
|
||||
"lng_context_edit_permissions" = "Edit permissions";
|
||||
|
@ -719,6 +719,18 @@ void ApiWrap::applyFeedDialogs(
|
||||
_session->data().sendHistoryChangeNotifications();
|
||||
}
|
||||
|
||||
void ApiWrap::changeDialogUnreadMark(
|
||||
not_null<History*> history,
|
||||
bool unread) {
|
||||
history->setUnreadMark(unread);
|
||||
|
||||
using Flag = MTPmessages_MarkDialogUnread::Flag;
|
||||
request(MTPmessages_MarkDialogUnread(
|
||||
MTP_flags(unread ? Flag::f_unread : Flag(0)),
|
||||
MTP_inputDialogPeer(history->peer->input)
|
||||
)).send();
|
||||
}
|
||||
|
||||
void ApiWrap::requestFullPeer(PeerData *peer) {
|
||||
if (!peer || _fullPeerRequests.contains(peer)) return;
|
||||
|
||||
@ -4417,6 +4429,9 @@ void ApiWrap::readServerHistory(not_null<History*> history) {
|
||||
if (history->unreadCount()) {
|
||||
readServerHistoryForce(history);
|
||||
}
|
||||
if (history->unreadMark()) {
|
||||
changeDialogUnreadMark(history, false);
|
||||
}
|
||||
}
|
||||
|
||||
void ApiWrap::readServerHistoryForce(not_null<History*> history) {
|
||||
|
@ -85,6 +85,8 @@ public:
|
||||
//void setFeedChannels(
|
||||
// not_null<Data::Feed*> feed,
|
||||
// const std::vector<not_null<ChannelData*>> &channels);
|
||||
void changeDialogUnreadMark(not_null<History*> history, bool unread);
|
||||
//void changeDialogUnreadMark(not_null<Data::Feed*> feed, bool unread); // #feed
|
||||
|
||||
void requestFullPeer(PeerData *peer);
|
||||
void requestPeer(PeerData *peer);
|
||||
|
@ -455,6 +455,10 @@ int Feed::chatListUnreadCount() const {
|
||||
return unreadCount();
|
||||
}
|
||||
|
||||
bool Feed::chatListUnreadMark() const {
|
||||
return false; // #feed unread mark
|
||||
}
|
||||
|
||||
bool Feed::chatListMutedBadge() const {
|
||||
return _unreadCount ? (*_unreadCount <= _unreadMutedCount) : false;
|
||||
}
|
||||
|
@ -63,6 +63,7 @@ public:
|
||||
bool toImportant() const override;
|
||||
bool shouldBeInChatList() const override;
|
||||
int chatListUnreadCount() const override;
|
||||
bool chatListUnreadMark() const override;
|
||||
bool chatListMutedBadge() const override;
|
||||
HistoryItem *chatsListItem() const override;
|
||||
const QString &chatsListName() const override;
|
||||
|
@ -72,6 +72,7 @@ public:
|
||||
virtual bool toImportant() const = 0;
|
||||
virtual bool shouldBeInChatList() const = 0;
|
||||
virtual int chatListUnreadCount() const = 0;
|
||||
virtual bool chatListUnreadMark() const = 0;
|
||||
virtual bool chatListMutedBadge() const = 0;
|
||||
virtual HistoryItem *chatsListItem() const = 0;
|
||||
virtual const QString &chatsListName() const = 0;
|
||||
|
@ -407,10 +407,11 @@ void RowPainter::paint(
|
||||
const auto history = row->history();
|
||||
const auto peer = history ? history->peer.get() : nullptr;
|
||||
const auto unreadCount = entry->chatListUnreadCount();
|
||||
const auto unreadMark = entry->chatListUnreadMark();
|
||||
const auto unreadMuted = entry->chatListMutedBadge();
|
||||
const auto item = entry->chatsListItem();
|
||||
const auto cloudDraft = [&]() -> const Data::Draft*{
|
||||
if (history && (!item || !unreadCount)) {
|
||||
if (history && (!item || (!unreadCount && !unreadMark))) {
|
||||
// Draw item, if there are unread messages.
|
||||
if (const auto draft = history->cloudDraft()) {
|
||||
if (!Data::draftIsNull(draft)) {
|
||||
@ -458,11 +459,18 @@ void RowPainter::paint(
|
||||
}
|
||||
return (unreadCount > 0);
|
||||
}();
|
||||
const auto displayUnreadMark = !displayUnreadCounter
|
||||
&& !displayMentionBadge
|
||||
&& history
|
||||
&& unreadMark;
|
||||
const auto displayPinnedIcon = !displayUnreadCounter
|
||||
&& !displayMentionBadge
|
||||
&& !displayUnreadMark
|
||||
&& entry->isPinnedDialog();
|
||||
if (displayUnreadCounter) {
|
||||
auto counter = QString::number(unreadCount);
|
||||
if (displayUnreadCounter || displayUnreadMark) {
|
||||
auto counter = (unreadCount > 0)
|
||||
? QString::number(unreadCount)
|
||||
: QString();
|
||||
auto unreadRight = fullWidth - st::dialogsPadding.x();
|
||||
auto unreadTop = texttop + st::dialogsTextFont->ascent - st::dialogsUnreadFont->ascent - (st::dialogsUnreadHeight - st::dialogsUnreadFont->height) / 2;
|
||||
auto unreadWidth = 0;
|
||||
|
@ -1645,6 +1645,11 @@ int History::unreadCount() const {
|
||||
return _unreadCount ? *_unreadCount : 0;
|
||||
}
|
||||
|
||||
int History::historiesUnreadCount() const {
|
||||
const auto result = unreadCount();
|
||||
return (!result && unreadMark()) ? 1 : result;
|
||||
}
|
||||
|
||||
bool History::unreadCountKnown() const {
|
||||
return !!_unreadCount;
|
||||
}
|
||||
@ -1673,6 +1678,16 @@ void History::setUnreadCount(int newUnreadCount) {
|
||||
calculateFirstUnreadMessage();
|
||||
}
|
||||
}
|
||||
const auto unreadMarkDelta = [&] {
|
||||
if (_unreadMark) {
|
||||
const auto was = _unreadCount && (*_unreadCount > 0);
|
||||
const auto now = (newUnreadCount > 0);
|
||||
if (was != now) {
|
||||
return was ? 1 : -1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}();
|
||||
_unreadCount = newUnreadCount;
|
||||
|
||||
if (_unreadBarView) {
|
||||
@ -1685,16 +1700,40 @@ void History::setUnreadCount(int newUnreadCount) {
|
||||
}
|
||||
|
||||
if (inChatList(Dialogs::Mode::All)) {
|
||||
const auto delta = unreadCountDelta
|
||||
? *unreadCountDelta
|
||||
: newUnreadCount;
|
||||
App::histories().unreadIncrement(
|
||||
unreadCountDelta ? *unreadCountDelta : newUnreadCount,
|
||||
delta + unreadMarkDelta,
|
||||
mute());
|
||||
}
|
||||
if (const auto main = App::main()) {
|
||||
main->unreadCountChanged(this);
|
||||
}
|
||||
Notify::peerUpdatedDelayed(
|
||||
peer,
|
||||
Notify::PeerUpdate::Flag::UnreadViewChanged);
|
||||
}
|
||||
}
|
||||
|
||||
void History::setUnreadMark(bool unread) {
|
||||
if (_unreadMark != unread) {
|
||||
_unreadMark = unread;
|
||||
if (!_unreadCount || !*_unreadCount) {
|
||||
if (inChatList(Dialogs::Mode::All)) {
|
||||
const auto delta = _unreadMark ? 1 : -1;
|
||||
App::histories().unreadIncrement(delta, mute());
|
||||
|
||||
updateChatListEntry();
|
||||
}
|
||||
}
|
||||
Notify::peerUpdatedDelayed(
|
||||
peer,
|
||||
Notify::PeerUpdate::Flag::UnreadViewChanged);
|
||||
}
|
||||
}
|
||||
|
||||
bool History::unreadMark() const {
|
||||
return _unreadMark;
|
||||
}
|
||||
|
||||
void History::changeUnreadCount(int delta) {
|
||||
if (_unreadCount) {
|
||||
setUnreadCount(std::max(*_unreadCount + delta, 0));
|
||||
@ -1733,8 +1772,8 @@ bool History::changeMute(bool newMute) {
|
||||
}
|
||||
}
|
||||
if (inChatList(Dialogs::Mode::All)) {
|
||||
if (_unreadCount && *_unreadCount) {
|
||||
App::histories().unreadMuteChanged(*_unreadCount, _mute);
|
||||
if (const auto count = historiesUnreadCount()) {
|
||||
App::histories().unreadMuteChanged(count, _mute);
|
||||
Notify::unreadCounterUpdated();
|
||||
}
|
||||
Notify::historyMuteUpdated(this);
|
||||
@ -1947,8 +1986,7 @@ not_null<HistoryItem*> History::addNewInTheMiddle(
|
||||
return item;
|
||||
}
|
||||
|
||||
int History::chatListUnreadCount() const {
|
||||
const auto result = unreadCount();
|
||||
History *History::migrateSibling() const {
|
||||
const auto addFromId = [&] {
|
||||
if (const auto from = peer->migrateFrom()) {
|
||||
return from->id;
|
||||
@ -1957,12 +1995,26 @@ int History::chatListUnreadCount() const {
|
||||
}
|
||||
return PeerId(0);
|
||||
}();
|
||||
if (const auto migrated = App::historyLoaded(addFromId)) {
|
||||
return App::historyLoaded(addFromId);
|
||||
}
|
||||
|
||||
int History::chatListUnreadCount() const {
|
||||
const auto result = unreadCount();
|
||||
if (const auto migrated = migrateSibling()) {
|
||||
return result + migrated->unreadCount();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
bool History::chatListUnreadMark() const {
|
||||
if (unreadMark()) {
|
||||
return true;
|
||||
} else if (const auto migrated = migrateSibling()) {
|
||||
return migrated->unreadMark();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool History::chatListMutedBadge() const {
|
||||
return mute();
|
||||
}
|
||||
@ -2201,6 +2253,7 @@ void History::applyDialog(const MTPDdialog &data) {
|
||||
data.vread_inbox_max_id.v,
|
||||
data.vread_outbox_max_id.v);
|
||||
applyDialogTopMessage(data.vtop_message.v);
|
||||
setUnreadMark(data.is_unread_mark());
|
||||
setUnreadMentionsCount(data.vunread_mentions_count.v);
|
||||
if (const auto channel = peer->asChannel()) {
|
||||
if (data.has_pts()) {
|
||||
@ -2650,9 +2703,10 @@ void History::applyGroupAdminChanges(
|
||||
}
|
||||
|
||||
void History::changedInChatListHook(Dialogs::Mode list, bool added) {
|
||||
if (list == Dialogs::Mode::All && unreadCount()) {
|
||||
const auto delta = added ? unreadCount() : -unreadCount();
|
||||
App::histories().unreadIncrement(delta, mute());
|
||||
if (list == Dialogs::Mode::All) {
|
||||
if (const auto delta = historiesUnreadCount() * (added ? 1 : -1)) {
|
||||
App::histories().unreadIncrement(delta, mute());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -213,6 +213,9 @@ public:
|
||||
bool unreadCountKnown() const;
|
||||
void setUnreadCount(int newUnreadCount);
|
||||
void changeUnreadCount(int delta);
|
||||
void setUnreadMark(bool unread);
|
||||
bool unreadMark() const;
|
||||
int historiesUnreadCount() const; // unreadCount || unreadMark ? 1 : 0.
|
||||
bool mute() const;
|
||||
bool changeMute(bool newMute);
|
||||
void addUnreadBar();
|
||||
@ -322,6 +325,7 @@ public:
|
||||
HistoryItemsList validateForwardDraft();
|
||||
void setForwardDraft(MessageIdsList &&items);
|
||||
|
||||
History *migrateSibling() const;
|
||||
bool useProxyPromotion() const override;
|
||||
void updateChatListExistence() override;
|
||||
bool shouldBeInChatList() const override;
|
||||
@ -329,6 +333,7 @@ public:
|
||||
return !mute();
|
||||
}
|
||||
int chatListUnreadCount() const override;
|
||||
bool chatListUnreadMark() const override;
|
||||
bool chatListMutedBadge() const override;
|
||||
HistoryItem *chatsListItem() const override;
|
||||
const QString &chatsListName() const override;
|
||||
@ -492,6 +497,7 @@ private:
|
||||
base::optional<int> _unreadMentionsCount;
|
||||
base::flat_set<MsgId> _unreadMentions;
|
||||
base::optional<HistoryItem*> _lastMessage;
|
||||
bool _unreadMark = false;
|
||||
|
||||
// A pointer to the block that is currently being built.
|
||||
// We hold this pointer so we can destroy it while building
|
||||
|
@ -641,6 +641,7 @@ HistoryWidget::HistoryWidget(
|
||||
using UpdateFlag = Notify::PeerUpdate::Flag;
|
||||
auto changes = UpdateFlag::ChannelRightsChanged
|
||||
| UpdateFlag::UnreadMentionsChanged
|
||||
| UpdateFlag::UnreadViewChanged
|
||||
| UpdateFlag::MigrationChanged
|
||||
| UpdateFlag::RestrictionReasonChanged
|
||||
| UpdateFlag::ChannelPinnedChanged
|
||||
@ -659,6 +660,9 @@ HistoryWidget::HistoryWidget(
|
||||
if (update.flags & UpdateFlag::UnreadMentionsChanged) {
|
||||
updateUnreadMentionsVisibility();
|
||||
}
|
||||
if (update.flags & UpdateFlag::UnreadViewChanged) {
|
||||
unreadCountUpdated();
|
||||
}
|
||||
if (update.flags & UpdateFlag::MigrationChanged) {
|
||||
if (auto channel = _peer->migrateTo()) {
|
||||
Ui::showPeerHistory(channel, ShowAtUnreadMsgId);
|
||||
@ -1913,7 +1917,19 @@ void HistoryWidget::showHistory(const PeerId &peerId, MsgId showAtMsgId, bool re
|
||||
}
|
||||
}
|
||||
}
|
||||
unreadCountChanged(_history); // set _historyDown badge.
|
||||
if (_history->chatListUnreadMark()) {
|
||||
Auth().api().changeDialogUnreadMark(_history, false);
|
||||
if (_migrated) {
|
||||
Auth().api().changeDialogUnreadMark(_migrated, false);
|
||||
}
|
||||
|
||||
// Must be done before unreadCountUpdated(), or we auto-close.
|
||||
_history->setUnreadMark(false);
|
||||
if (_migrated) {
|
||||
_migrated->setUnreadMark(false);
|
||||
}
|
||||
}
|
||||
unreadCountUpdated(); // set _historyDown badge.
|
||||
} else {
|
||||
_topBar->setActiveChat(Dialogs::Key());
|
||||
updateTopBarSelection();
|
||||
@ -2366,8 +2382,15 @@ void HistoryWidget::historyToDown(History *history) {
|
||||
}
|
||||
}
|
||||
|
||||
void HistoryWidget::unreadCountChanged(not_null<History*> history) {
|
||||
if (history == _history || history == _migrated) {
|
||||
void HistoryWidget::unreadCountUpdated() {
|
||||
if (_history->chatListUnreadMark()) {
|
||||
crl::on_main(this, [=, history = _history] {
|
||||
if (history == _history) {
|
||||
controller()->showBackFromStack();
|
||||
emit cancelled();
|
||||
}
|
||||
});
|
||||
} else {
|
||||
updateHistoryDownVisibility();
|
||||
_historyDown->setUnreadCount(_history->chatListUnreadCount());
|
||||
}
|
||||
@ -2376,7 +2399,9 @@ void HistoryWidget::unreadCountChanged(not_null<History*> history) {
|
||||
bool HistoryWidget::messagesFailed(const RPCError &error, mtpRequestId requestId) {
|
||||
if (MTP::isDefaultHandledError(error)) return false;
|
||||
|
||||
if (error.type() == qstr("CHANNEL_PRIVATE") || error.type() == qstr("CHANNEL_PUBLIC_GROUP_NA") || error.type() == qstr("USER_BANNED_IN_CHANNEL")) {
|
||||
if (error.type() == qstr("CHANNEL_PRIVATE")
|
||||
|| error.type() == qstr("CHANNEL_PUBLIC_GROUP_NA")
|
||||
|| error.type() == qstr("USER_BANNED_IN_CHANNEL")) {
|
||||
auto was = _peer;
|
||||
controller()->showBackFromStack();
|
||||
Ui::show(Box<InformBox>(lang((was && was->isMegagroup()) ? lng_group_not_accessible : lng_channel_not_accessible)));
|
||||
|
@ -211,7 +211,6 @@ public:
|
||||
not_null<History*> history,
|
||||
not_null<HistoryItem*> item);
|
||||
void historyToDown(History *history);
|
||||
void unreadCountChanged(not_null<History*> history);
|
||||
|
||||
QRect historyRect() const;
|
||||
void pushTabbedSelectorToThirdSection(
|
||||
@ -449,6 +448,7 @@ private:
|
||||
void forwardItems(MessageIdsList &&items);
|
||||
void handleHistoryChange(not_null<const History*> history);
|
||||
void refreshAboutProxyPromotion();
|
||||
void unreadCountUpdated();
|
||||
|
||||
void highlightMessage(MsgId universalMessageId);
|
||||
void adjustHighlightedMessageToMigrated();
|
||||
|
@ -1275,10 +1275,6 @@ Dialogs::IndexedList *MainWidget::contactsNoDialogsList() {
|
||||
return _dialogs->contactsNoDialogsList();
|
||||
}
|
||||
|
||||
void MainWidget::unreadCountChanged(not_null<History*> history) {
|
||||
_history->unreadCountChanged(history);
|
||||
}
|
||||
|
||||
TimeMs MainWidget::highlightStartTime(not_null<const HistoryItem*> item) const {
|
||||
return _history->highlightStartTime(item);
|
||||
}
|
||||
@ -4634,8 +4630,14 @@ void MainWidget::feedUpdate(const MTPUpdate &update) {
|
||||
|
||||
case mtpc_updateDialogUnreadMark: {
|
||||
const auto &data = update.c_updateDialogUnreadMark();
|
||||
if (data.is_unread()) {
|
||||
// #TODO dialog_unread
|
||||
const auto history = data.vpeer.match(
|
||||
[&](const MTPDdialogPeer &data) {
|
||||
const auto peerId = peerFromMTP(data.vpeer);
|
||||
return App::historyLoaded(peerId);
|
||||
//}, [&](const MTPDdialogPeerFeed &data) { // #feed
|
||||
});
|
||||
if (history) {
|
||||
history->setUnreadMark(data.is_unread());
|
||||
}
|
||||
} break;
|
||||
|
||||
|
@ -222,8 +222,6 @@ public:
|
||||
Dialogs::IndexedList *dialogsList();
|
||||
Dialogs::IndexedList *contactsNoDialogsList();
|
||||
|
||||
void unreadCountChanged(not_null<History*> history);
|
||||
|
||||
// While HistoryInner is not HistoryView::ListWidget.
|
||||
TimeMs highlightStartTime(not_null<const HistoryItem*> item) const;
|
||||
bool historyInSelectionMode() const;
|
||||
|
@ -37,13 +37,14 @@ struct PeerUpdate {
|
||||
MigrationChanged = (1 << 6),
|
||||
PinnedChanged = (1 << 7),
|
||||
RestrictionReasonChanged = (1 << 8),
|
||||
UnreadViewChanged = (1 << 9),
|
||||
|
||||
// For chats and channels
|
||||
InviteLinkChanged = (1 << 9),
|
||||
MembersChanged = (1 << 10),
|
||||
AdminsChanged = (1 << 11),
|
||||
BannedUsersChanged = (1 << 12),
|
||||
UnreadMentionsChanged = (1 << 13),
|
||||
InviteLinkChanged = (1 << 10),
|
||||
MembersChanged = (1 << 11),
|
||||
AdminsChanged = (1 << 12),
|
||||
BannedUsersChanged = (1 << 13),
|
||||
UnreadMentionsChanged = (1 << 14),
|
||||
|
||||
// For users
|
||||
UserCanShareContact = (1 << 16),
|
||||
|
@ -50,6 +50,7 @@ private:
|
||||
void addPinToggle();
|
||||
void addInfo();
|
||||
void addSearch();
|
||||
void addToggleUnreadMark();
|
||||
void addUserActions(not_null<UserData*> user);
|
||||
void addBlockUser(not_null<UserData*> user);
|
||||
void addChatActions(not_null<ChatData*> chat);
|
||||
@ -229,6 +230,48 @@ void Filler::addSearch() {
|
||||
});
|
||||
}
|
||||
|
||||
void Filler::addToggleUnreadMark() {
|
||||
const auto peer = _peer;
|
||||
const auto isUnread = [](not_null<PeerData*> peer) {
|
||||
if (const auto history = App::historyLoaded(peer)) {
|
||||
return (history->chatListUnreadCount() > 0)
|
||||
|| (history->chatListUnreadMark());
|
||||
}
|
||||
return false;
|
||||
};
|
||||
const auto label = [=](not_null<PeerData*> peer) {
|
||||
return lang(isUnread(peer)
|
||||
? lng_context_mark_read
|
||||
: lng_context_mark_unread);
|
||||
};
|
||||
auto action = _addAction(label(peer), [=] {
|
||||
const auto markAsRead = isUnread(peer);
|
||||
const auto handle = [&](not_null<History*> history) {
|
||||
if (markAsRead) {
|
||||
Auth().api().readServerHistory(history);
|
||||
} else {
|
||||
Auth().api().changeDialogUnreadMark(history, !markAsRead);
|
||||
}
|
||||
};
|
||||
const auto history = App::history(peer);
|
||||
handle(history);
|
||||
if (markAsRead) {
|
||||
if (const auto migrated = history->migrateSibling()) {
|
||||
handle(migrated);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
auto lifetime = Notify::PeerUpdateViewer(
|
||||
_peer,
|
||||
Notify::PeerUpdate::Flag::UnreadViewChanged
|
||||
) | rpl::start_with_next([=] {
|
||||
action->setText(label(peer));
|
||||
});
|
||||
|
||||
Ui::AttachAsChild(action, std::move(lifetime));
|
||||
}
|
||||
|
||||
void Filler::addBlockUser(not_null<UserData*> user) {
|
||||
auto blockText = [](not_null<UserData*> user) {
|
||||
return lang(user->isBlocked()
|
||||
@ -401,6 +444,7 @@ void Filler::fill() {
|
||||
}
|
||||
if (_source == PeerMenuSource::ChatsList) {
|
||||
addSearch();
|
||||
addToggleUnreadMark();
|
||||
}
|
||||
|
||||
if (const auto user = _peer->asUser()) {
|
||||
|
Loading…
Reference in New Issue
Block a user