Display title and userpic of archived chats.

This commit is contained in:
John Preston 2019-04-16 12:50:59 +04:00
parent 9bf8a8108d
commit 76c3e9a529
19 changed files with 418 additions and 324 deletions

View File

@ -304,6 +304,7 @@ historyPeer8NameFgSelected: historyPeer8NameFg; // orange group member name in a
historyPeer8UserpicBg: #faa774; // orange userpic background
historyPeerUserpicFg: windowFgActive; // default userpic initials
historyPeerSavedMessagesBg: historyPeer4UserpicBg; // saved messages userpic background
historyPeerArchiveUserpicBg: historyPeer2UserpicBg; // archive folder userpic background
// Some values are marked as (adjusted), it means they're adjusted by
// hue and saturation of the average background color if user chooses

Binary file not shown.

After

Width:  |  Height:  |  Size: 449 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 814 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

@ -1192,6 +1192,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_channel_mute" = "Mute";
"lng_channel_unmute" = "Unmute";
"lng_saved_messages" = "Saved Messages";
"lng_archived_chats" = "Archived chats";
"lng_saved_short" = "Save";
"lng_saved_forward_here" = "Forward messages here for quick access";
@ -1267,7 +1268,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_context_view_profile" = "View profile";
"lng_context_view_group" = "View group info";
"lng_context_view_channel" = "View channel info";
"lng_context_view_feed_info" = "View feed info";
//"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";
@ -1686,32 +1687,33 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_admin_log_admin_pin_messages" = "Pin messages";
"lng_admin_log_admin_add_admins" = "Add new admins";
"lng_feed_name" = "Feed";
"lng_feed_show_next" = "Show Next";
// #feed
//"lng_feed_name" = "Feed";
//"lng_feed_show_next" = "Show Next";
"lng_feed_group" = "Group in feed";
"lng_feed_ungroup" = "Ungroup from feed";
"lng_feed_channel_added" = "Channel added to your feed.";
"lng_feed_channel_removed" = "Channel removed from your feed.";
"lng_feed_no_messages" = "No messages in this feed yet";
"lng_feed_channels#one" = "{count} channel";
"lng_feed_channels#other" = "{count} channels";
"lng_feed_notifications" = "Feed notifications";
"lng_feed_ungroup_all" = "Ungroup all channels";
"lng_feed_sure_ungroup_all" = "Are you sure you want to ungroup all channels from this feed?";
"lng_feed_ungroup_sure" = "Ungroup";
"lng_feed_create_new" = "New feed";
"lng_feed_too_few_channels#one" = "You need at least {count} channel to create a feed.";
"lng_feed_too_few_channels#other" = "You need at least {count} channels to create a feed.";
"lng_feed_select_more_channels#one" = "Select {count} channel or more.";
"lng_feed_select_more_channels#other" = "Select {count} channels or more.";
"lng_feed_create" = "Create";
"lng_feed_edit_title" = "Edit feed";
"lng_feed_channels_not_found" = "No channels found";
//"lng_feed_group" = "Group in feed";
//"lng_feed_ungroup" = "Ungroup from feed";
//"lng_feed_channel_added" = "Channel added to your feed.";
//"lng_feed_channel_removed" = "Channel removed from your feed.";
//"lng_feed_no_messages" = "No messages in this feed yet";
//"lng_feed_channels#one" = "{count} channel";
//"lng_feed_channels#other" = "{count} channels";
//"lng_feed_notifications" = "Feed notifications";
//"lng_feed_ungroup_all" = "Ungroup all channels";
//"lng_feed_sure_ungroup_all" = "Are you sure you want to ungroup all channels from this feed?";
//"lng_feed_ungroup_sure" = "Ungroup";
//"lng_feed_create_new" = "New feed";
//"lng_feed_too_few_channels#one" = "You need at least {count} channel to create a feed.";
//"lng_feed_too_few_channels#other" = "You need at least {count} channels to create a feed.";
//"lng_feed_select_more_channels#one" = "Select {count} channel or more.";
//"lng_feed_select_more_channels#other" = "Select {count} channels or more.";
//"lng_feed_create" = "Create";
//"lng_feed_edit_title" = "Edit feed";
//"lng_feed_channels_not_found" = "No channels found";
"lng_info_feed_title" = "Feed Info";
"lng_info_feed_is_default" = "Group new channels";
"lng_info_feed_channels" = "Channels";
//"lng_info_feed_title" = "Feed Info";
//"lng_info_feed_is_default" = "Group new channels";
//"lng_info_feed_channels" = "Channels";
"lng_terms_signup" = "By signing up,\nyou agree to the {link}.";
"lng_terms_signup_link" = "Terms of Service";

View File

@ -433,38 +433,39 @@ void ApiWrap::savePinnedOrder() {
MTP_vector(peers)
)).send();
}
void ApiWrap::toggleHistoryArchived(
not_null<History*> history,
bool archived,
Fn<void()> callback) {
if (const auto already = _historyArchivedRequests.take(history)) {
request(already->first).cancel();
}
// #TODO archive
const auto folderId = Data::Folder::kId;
//const auto flags = group
// ? MTPchannels_ChangeFeedBroadcast::Flag::f_feed_id
// : MTPchannels_ChangeFeedBroadcast::Flag(0);
//const auto requestId = request(MTPchannels_ChangeFeedBroadcast(
// MTP_flags(flags),
// channel->inputChannel,
// MTP_int(feedId)
//)).done([=](const MTPUpdates &result) {
// applyUpdates(result);
// if (group) {
// channel->setFeed(_session->data().feed(feedId));
// } else {
// channel->clearFeed();
// }
// if (const auto data = _channelGroupingRequests.take(channel)) {
// data->second();
// }
//}).fail([=](const RPCError &error) {
// _channelGroupingRequests.remove(channel);
//}).send();
//_channelGroupingRequests.emplace(channel, requestId, callback);
}
// #feed
//void ApiWrap::toggleChannelGrouping(
// not_null<ChannelData*> channel,
// bool group,
// Fn<void()> callback) {
// if (const auto already = _channelGroupingRequests.take(channel)) {
// request(already->first).cancel();
// }
// const auto feedId = Data::Feed::kId;
// const auto flags = group
// ? MTPchannels_ChangeFeedBroadcast::Flag::f_feed_id
// : MTPchannels_ChangeFeedBroadcast::Flag(0);
// const auto requestId = request(MTPchannels_ChangeFeedBroadcast(
// MTP_flags(flags),
// channel->inputChannel,
// MTP_int(feedId)
// )).done([=](const MTPUpdates &result) {
// applyUpdates(result);
// if (group) {
// channel->setFeed(_session->data().feed(feedId));
// } else {
// channel->clearFeed();
// }
// if (const auto data = _channelGroupingRequests.take(channel)) {
// data->second();
// }
// }).fail([=](const RPCError &error) {
// _channelGroupingRequests.remove(channel);
// }).send();
// _channelGroupingRequests.emplace(channel, requestId, callback);
//}
//
//void ApiWrap::ungroupAllFromFeed(not_null<Data::Feed*> feed) {
// const auto flags = MTPchannels_SetFeedBroadcasts::Flag::f_channels
// | MTPchannels_SetFeedBroadcasts::Flag::f_also_newly_joined;
@ -3597,6 +3598,23 @@ void ApiWrap::applyUpdateNoPtsCheck(const MTPUpdate &update) {
Q_UNUSED(d); // Web page was updated anyway.
} break;
case mtpc_updateFolderPeers: {
const auto &data = update.c_updateFolderPeers();
auto &owner = _session->data();
for (const auto &peer : data.vfolder_peers.v) {
peer.match([&](const MTPDfolderPeer &data) {
const auto peerId = peerFromMTP(data.vpeer);
if (const auto history = owner.historyLoaded(peerId)) {
if (const auto folderId = data.vfolder_id.v) {
history->setFolder(owner.folder(folderId));
} else {
history->clearFolder();
}
}
});
}
} break;
case mtpc_updateDeleteMessages: {
auto &d = update.c_updateDeleteMessages();
App::feedWereDeleted(NoChannel, d.vmessages.v);

View File

@ -65,11 +65,11 @@ public:
void applyUpdates(const MTPUpdates &updates, uint64 sentMessageRandomId = 0);
void savePinnedOrder();
//void toggleChannelGrouping( // #feed
// not_null<ChannelData*> channel,
// bool group,
// Fn<void()> callback);
//void ungroupAllFromFeed(not_null<Data::Feed*> feed);
void toggleHistoryArchived(
not_null<History*> history,
bool archived,
Fn<void()> callback);
//void ungroupAllFromFeed(not_null<Data::Feed*> feed); // #feed
using RequestMessageDataCallback = Fn<void(ChannelData*, MsgId)>;
void requestMessageData(
@ -651,8 +651,8 @@ private:
Fn<void(
const MTPchannels_ChannelParticipants&)> _channelMembersForAddCallback;
base::flat_map<
not_null<ChannelData*>,
std::pair<mtpRequestId,Fn<void()>>> _channelGroupingRequests;
not_null<History*>,
std::pair<mtpRequestId,Fn<void()>>> _historyArchivedRequests;
using KickRequest = std::pair<
not_null<ChannelData*>,

View File

@ -49,6 +49,7 @@ addChildParentFlags('MTPDreplyKeyboardForceReply', 'MTPDreplyKeyboardMarkup');
addChildParentFlags('MTPDinputPeerNotifySettings', 'MTPDpeerNotifySettings');
addChildParentFlags('MTPDpeerNotifySettings', 'MTPDinputPeerNotifySettings');
addChildParentFlags('MTPDchannelForbidden', 'MTPDchannel');
addChildParentFlags('MTPDdialogFolder', 'MTPDdialog');
# this is a map (key flags -> map (flag name -> flag bit))
# each key flag of parentFlags should be a subset of the value flag here

View File

@ -306,27 +306,6 @@ void ChannelData::setAvailableMinId(MsgId availableMinId) {
}
}
}
// #TODO archive
//void ChannelData::setFeed(not_null<Data::Feed*> feed) {
// setFeedPointer(feed);
//}
//
//void ChannelData::clearFeed() {
// setFeedPointer(nullptr);
//}
//
//void ChannelData::setFeedPointer(Data::Feed *feed) {
// if (_feed != feed) {
// const auto was = _feed;
// _feed = feed;
// if (was) {
// was->unregisterOne(this);
// }
// if (_feed) {
// _feed->registerOne(this);
// }
// }
//}
bool ChannelData::canBanMembers() const {
return amCreator()

View File

@ -18,6 +18,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "auth_session.h"
#include "apiwrap.h"
#include "mainwidget.h"
#include "styles/style_dialogs.h" // st::dialogsArchiveUserpic
namespace Data {
@ -35,7 +36,7 @@ Folder::Folder(not_null<Data::Session*> owner, FolderId id)
: Entry(this)
, _id(id)
, _owner(owner)
, _name(lang(lng_feed_name)) {
, _name(lang(lng_archived_chats)) {
indexNameParts();
}
@ -77,83 +78,83 @@ void Folder::indexNameParts() {
}
}
void Folder::registerOne(not_null<PeerData*> peer) {
const auto history = owner().history(peer);
if (!base::contains(_chats, history)) {
const auto invisible = empty(_chats);
_chats.push_back(history);
//session().storage().invalidate( // #feed
// Storage::FeedMessagesInvalidate(_id));
void Folder::registerOne(not_null<History*> history) {
if (base::contains(_histories, history)) {
return;
}
const auto invisible = empty(_histories);
_histories.push_back(history);
//session().storage().invalidate( // #feed
// Storage::FeedMessagesInvalidate(_id));
if (history->chatListMessageKnown()) {
if (const auto last = history->chatListMessage()) {
if (justUpdateChatListMessage(last)) {
updateChatListEntry();
}
}
} else if (chatListMessageKnown()) {
history->requestChatListMessage();
}
if (unreadCountKnown()) {
if (history->unreadCountKnown()) {
// If history unreadCount is known that means that we've
// already had the channel information and if it was in the
// feed already (not yet known) it wouldn't get here.
// That means here we get if we add a new channel to feed.
if (const auto count = history->unreadCount()) {
unreadCountChanged(count, history->mute() ? count : 0);
}
} else if (!_settingChats) {
session().api().requestDialogEntry(this);
if (history->chatListMessageKnown()) {
if (const auto last = history->chatListMessage()) {
if (justUpdateChatListMessage(last)) {
updateChatListEntry();
}
}
if (invisible && !empty(_chats)) {
updateChatListExistence();
for (const auto history : _chats) {
history->updateChatListExistence();
} else if (chatListMessageKnown()) {
history->requestChatListMessage();
}
if (unreadCountKnown()) {
if (history->unreadCountKnown()) {
// If history unreadCount is known that means that we've
// already had the channel information and if it was in the
// feed already (not yet known) it wouldn't get here.
// That means here we get if we add a new channel to feed.
if (const auto count = history->unreadCount()) {
unreadCountChanged(count, history->mute() ? count : 0);
}
} else {
} else if (!_settingHistories) {
session().api().requestDialogEntry(this);
}
}
if (invisible && !empty(_histories)) {
updateChatListExistence();
for (const auto history : _histories) {
history->updateChatListExistence();
}
_owner->notifyFolderUpdated(this, FolderUpdateFlag::List);
} else {
history->updateChatListExistence();
}
_owner->notifyFolderUpdated(this, FolderUpdateFlag::List);
}
void Folder::unregisterOne(not_null<PeerData*> peer) {
const auto history = owner().history(peer);
const auto i = ranges::remove(_chats, history);
if (i != end(_chats)) {
const auto visible = !empty(_chats);
_chats.erase(i, end(_chats));
//session().storage().remove( // #feed
// Storage::FeedMessagesRemoveAll(_id, channel->bareId()));
void Folder::unregisterOne(not_null<History*> history) {
const auto i = ranges::remove(_histories, history);
if (i == end(_histories)) {
return;
}
const auto visible = !empty(_histories);
_histories.erase(i, end(_histories));
//session().storage().remove( // #feed
// Storage::FeedMessagesRemoveAll(_id, channel->bareId()));
if (chatListMessageKnown()) {
if (const auto last = chatListMessage()) {
if (last->history() == history) {
recountChatListMessage();
}
if (chatListMessageKnown()) {
if (const auto last = chatListMessage()) {
if (last->history() == history) {
recountChatListMessage();
}
}
if (unreadCountKnown()) {
if (history->unreadCountKnown()) {
if (const auto delta = -history->unreadCount()) {
unreadCountChanged(delta, history->mute() ? delta : 0);
}
} else {
session().api().requestDialogEntry(this);
}
}
if (visible && empty(_chats)) {
updateChatListExistence();
for (const auto history : _chats) {
history->updateChatListExistence();
}
if (unreadCountKnown()) {
if (history->unreadCountKnown()) {
if (const auto delta = -history->unreadCount()) {
unreadCountChanged(delta, history->mute() ? delta : 0);
}
} else {
session().api().requestDialogEntry(this);
}
}
if (visible && empty(_histories)) {
updateChatListExistence();
for (const auto history : _histories) {
history->updateChatListExistence();
}
_owner->notifyFolderUpdated(this, FolderUpdateFlag::List);
} else {
history->updateChatListExistence();
}
_owner->notifyFolderUpdated(this, FolderUpdateFlag::List);
}
void Folder::updateChatListMessage(not_null<HistoryItem*> item) {
@ -167,7 +168,7 @@ void Folder::updateChatListMessage(not_null<HistoryItem*> item) {
void Folder::loadUserpic() {
//constexpr auto kPaintUserpicsCount = 4; // #feed
//auto load = kPaintUserpicsCount;
//for (const auto history : _chats) {
//for (const auto history : _histories) {
// history->peer->loadUserpic();
// if (!--load) {
// break;
@ -180,10 +181,17 @@ void Folder::paintUserpic(
int x,
int y,
int size) const {
p.setPen(Qt::NoPen);
p.setBrush(st::historyPeerArchiveUserpicBg);
{
PainterHighQualityEnabler hq(p);
p.drawRoundedRect(x, y, size, size, size / 3., size / 3.);
}
st::dialogsArchiveUserpic.paintInCenter(p, { x, y, size, size });
//const auto small = (size - st::lineWidth) / 2; // #feed
//const auto delta = size - small;
//auto index = 0;
//for (const auto history : _chats) {
//for (const auto history : _histories) {
// history->peer->paintUserpic(p, x, y, small);
// switch (++index) {
// case 1:
@ -194,76 +202,76 @@ void Folder::paintUserpic(
//}
}
const std::vector<not_null<History*>> &Folder::chats() const {
return _chats;
const std::vector<not_null<History*>> &Folder::histories() const {
return _histories;
}
int32 Folder::chatsHash() const {
const auto ordered = ranges::view::all(
_chats
) | ranges::view::transform([](not_null<History*> history) {
return history->peer->bareId();
}) | ranges::to_vector | ranges::action::sort;
return Api::CountHash(ordered);
bool Folder::historiesLoaded() const {
return _historiesLoaded;
}
bool Folder::chatsLoaded() const {
return _chatsLoaded;
}
void Folder::setChatsLoaded(bool loaded) {
if (_chatsLoaded != loaded) {
_chatsLoaded = loaded;
void Folder::setHistoriesLoaded(bool loaded) {
if (_historiesLoaded != loaded) {
_historiesLoaded = loaded;
_owner->notifyFolderUpdated(this, FolderUpdateFlag::List);
}
}
void Folder::setChats(std::vector<not_null<PeerData*>> chats) {
const auto remove = ranges::view::all(
_chats
) | ranges::view::transform([](not_null<History*> history) {
return history->peer;
}) | ranges::view::filter([&](not_null<PeerData*> peer) {
return !base::contains(chats, peer);
}) | ranges::to_vector;
const auto add = ranges::view::all(
chats
) | ranges::view::filter([&](not_null<PeerData*> peer) {
return ranges::find(
_chats,
peer,
[](auto history) { return history->peer; }
) == end(_chats);
}) | ranges::view::transform([](PeerData *peer) {
return not_null<PeerData*>(peer);
}) | ranges::to_vector;
changeChatsList(add, remove);
setChatsLoaded(true);
}
void Folder::changeChatsList(
const std::vector<not_null<PeerData*>> &add,
const std::vector<not_null<PeerData*>> &remove) {
_settingChats = true;
const auto restore = gsl::finally([&] { _settingChats = false; });
//for (const auto channel : remove) { // #TODO archive
// channel->clearFeed();
//}
//// We assume the last message was correct before requesting the list.
//// So we save it and don't allow channels from the list to change it.
//// After that we restore it.
const auto oldChatListMessage = base::take(_chatListMessage);
//for (const auto channel : add) {
// _chatListMessage = std::nullopt;
// channel->setFeed(this);
//}
_chatListMessage = oldChatListMessage;
}
// // #feed
//int32 Folder::chatsHash() const {
// const auto ordered = ranges::view::all(
// _histories
// ) | ranges::view::transform([](not_null<History*> history) {
// return history->peer->bareId();
// }) | ranges::to_vector | ranges::action::sort;
// return Api::CountHash(ordered);
//}
//
//void Folder::setChats(std::vector<not_null<PeerData*>> chats) {
// const auto remove = ranges::view::all(
// _histories
// ) | ranges::view::transform([](not_null<History*> history) {
// return history->peer;
// }) | ranges::view::filter([&](not_null<PeerData*> peer) {
// return !base::contains(chats, peer);
// }) | ranges::to_vector;
//
// const auto add = ranges::view::all(
// chats
// ) | ranges::view::filter([&](not_null<PeerData*> peer) {
// return ranges::find(
// _histories,
// peer,
// [](auto history) { return history->peer; }
// ) == end(_histories);
// }) | ranges::view::transform([](PeerData *peer) {
// return not_null<PeerData*>(peer);
// }) | ranges::to_vector;
//
// changeChatsList(add, remove);
//
// setChatsLoaded(true);
//}
//
//void Folder::changeChatsList(
// const std::vector<not_null<PeerData*>> &add,
// const std::vector<not_null<PeerData*>> &remove) {
// _settingChats = true;
// const auto restore = gsl::finally([&] { _settingChats = false; });
//
// for (const auto channel : remove) {
// channel->clearFeed();
// }
//
// //// We assume the last message was correct before requesting the list.
// //// So we save it and don't allow channels from the list to change it.
// //// After that we restore it.
// const auto oldChatListMessage = base::take(_chatListMessage);
// for (const auto channel : add) {
// _chatListMessage = std::nullopt;
// channel->setFeed(this);
// }
// _chatListMessage = oldChatListMessage;
//}
bool Folder::justUpdateChatListMessage(not_null<HistoryItem*> item) {
if (!_chatListMessage) {
@ -298,7 +306,7 @@ void Folder::requestChatListMessage() {
void Folder::recountChatListMessage() {
_chatListMessage = std::nullopt;
for (const auto history : _chats) {
for (const auto history : _histories) {
if (!history->chatListMessageKnown()) {
requestChatListMessage();
return;
@ -309,7 +317,7 @@ void Folder::recountChatListMessage() {
void Folder::setChatListMessageFromChannels() {
_chatListMessage = nullptr;
for (const auto history : _chats) {
for (const auto history : _histories) {
if (const auto last = history->chatListMessage()) {
justUpdateChatListMessage(last);
}
@ -336,36 +344,38 @@ rpl::producer<int> Folder::unreadCountValue() const {
bool Folder::unreadCountKnown() const {
return !!_unreadCount;
}
// #feed
//void Folder::applyDialog(const MTPDdialogFeed &data) {
// const auto addChannel = [&](ChannelId channelId) {
// if (const auto channel = owner().channelLoaded(channelId)) {
// channel->setFeed(this);
// }
// };
// for (const auto &channelId : data.vfeed_other_channels.v) {
// addChannel(channelId.v);
// }
//
// _chatListMessage = nullptr;
// if (const auto peerId = peerFromMTP(data.vpeer)) {
// if (const auto channelId = peerToChannel(peerId)) {
// addChannel(channelId);
// const auto fullId = FullMsgId(channelId, data.vtop_message.v);
// if (const auto item = App::histItemById(fullId)) {
// justUpdateChatListMessage(item);
// }
// }
// }
// updateChatListDate();
//
// setUnreadCounts(
// data.vunread_count.v,
// data.vunread_muted_count.v);
// if (data.has_read_max_position()) {
// setUnreadPosition(FeedPositionFromMTP(data.vread_max_position));
// }
//}
void Folder::applyDialog(const MTPDdialogFolder &data) {
//const auto addChannel = [&](ChannelId channelId) { // #feed
// if (const auto channel = owner().channelLoaded(channelId)) {
// channel->setFeed(this);
// }
//};
//for (const auto &channelId : data.vfeed_other_channels.v) {
// addChannel(channelId.v);
//}
_chatListMessage = nullptr;
if (const auto peerId = peerFromMTP(data.vpeer)) {
owner().history(peerId)->setFolder(this);
const auto fullId = FullMsgId(
peerToChannel(peerId),
data.vtop_message.v);
if (const auto item = App::histItemById(fullId)) {
justUpdateChatListMessage(item);
}
}
updateChatListDate();
setUnreadCounts(
data.vunread_unmuted_messages_count.v,
data.vunread_muted_messages_count.v);
//setUnreadMark(data.is_unread_mark());
//setUnreadMentionsCount(data.vunread_mentions_count.v);
//if (data.has_read_max_position()) { // #feed
// setUnreadPosition(FeedPositionFromMTP(data.vread_max_position));
//}
}
void Folder::changedInChatListHook(Dialogs::Mode list, bool added) {
if (list != Dialogs::Mode::All) {
@ -444,12 +454,12 @@ void Folder::setUnreadCounts(int unreadNonMutedCount, int unreadMutedCount) {
_unreadMutedCount = unreadMutedCount;
});
}
void Folder::setUnreadPosition(const MessagePosition &position) {
if (_unreadPosition.current() < position) {
_unreadPosition = position;
}
}
// #feed
//void Folder::setUnreadPosition(const MessagePosition &position) {
// if (_unreadPosition.current() < position) {
// _unreadPosition = position;
// }
//}
void Folder::unreadCountChanged(int unreadCountDelta, int mutedCountDelta) {
if (!unreadCountKnown()) {
@ -466,14 +476,38 @@ void Folder::unreadCountChanged(int unreadCountDelta, int mutedCountDelta) {
_unreadMutedCount += mutedCountDelta;
});
}
MessagePosition Folder::unreadPosition() const {
return _unreadPosition.current();
}
rpl::producer<MessagePosition> Folder::unreadPositionChanges() const {
return _unreadPosition.changes();
}
//
//void Folder::setUnreadMark(bool unread) {
// if (_unreadMark != unread) {
// _unreadMark = unread;
// if (!_unreadCount || !*_unreadCount) {
// if (inChatList(Dialogs::Mode::All)) {
// const auto delta = _unreadMark ? 1 : -1;
// _owner->unreadIncrement(delta, mute());
// _owner->unreadEntriesChanged(
// delta,
// mute() ? delta : 0);
//
// updateChatListEntry();
// }
// }
// Notify::peerUpdatedDelayed(
// peer,
// Notify::PeerUpdate::Flag::UnreadViewChanged);
// }
//}
//
//bool Folder::unreadMark() const {
// return _unreadMark;
//}
// #feed
//MessagePosition Folder::unreadPosition() const {
// return _unreadPosition.current();
//}
//
//rpl::producer<MessagePosition> Folder::unreadPositionChanges() const {
// return _unreadPosition.changes();
//}
bool Folder::toImportant() const {
return false; // TODO feeds workmode
@ -484,7 +518,7 @@ bool Folder::useProxyPromotion() const {
}
bool Folder::shouldBeInChatList() const {
return !empty(_chats);
return !empty(_histories);
}
int Folder::chatListUnreadCount() const {

View File

@ -41,22 +41,26 @@ public:
AuthSession &session() const;
FolderId id() const;
void registerOne(not_null<PeerData*> peer);
void unregisterOne(not_null<PeerData*> peer);
void registerOne(not_null<History*> history);
void unregisterOne(not_null<History*> history);
void updateChatListMessage(not_null<HistoryItem*> item);
void messageRemoved(not_null<HistoryItem*> item);
void historyCleared(not_null<History*> history);
//void applyDialog(const MTPDdialogFeed &data); // #feed
void applyDialog(const MTPDdialogFolder &data);
void setUnreadCounts(int unreadNonMutedCount, int unreadMutedCount);
void setUnreadPosition(const MessagePosition &position);
//void setUnreadPosition(const MessagePosition &position); // #feed
void unreadCountChanged(
int unreadCountDelta,
int mutedCountDelta);
rpl::producer<int> unreadCountValue() const;
MessagePosition unreadPosition() const;
rpl::producer<MessagePosition> unreadPositionChanges() const;
//MessagePosition unreadPosition() const; // #feed
//rpl::producer<MessagePosition> unreadPositionChanges() const; // #feed
//void setUnreadMark(bool unread);
//bool unreadMark() const;
//int unreadCountForBadge() const; // unreadCount || unreadMark ? 1 : 0.
int unreadCount() const;
bool unreadCountKnown() const;
@ -82,11 +86,11 @@ public:
int y,
int size) const override;
const std::vector<not_null<History*>> &chats() const;
int32 chatsHash() const;
bool chatsLoaded() const;
void setChatsLoaded(bool loaded);
void setChats(std::vector<not_null<PeerData*>> chats);
const std::vector<not_null<History*>> &histories() const;
bool historiesLoaded() const;
void setHistoriesLoaded(bool loaded);
//int32 chatsHash() const;
//void setChats(std::vector<not_null<PeerData*>> chats); // #feed
private:
void indexNameParts();
@ -103,9 +107,9 @@ private:
FolderId _id = 0;
not_null<Data::Session*> _owner;
std::vector<not_null<History*>> _chats;
bool _settingChats = false;
bool _chatsLoaded = false;
std::vector<not_null<History*>> _histories;
bool _settingHistories = false;
bool _historiesLoaded = false;
QString _name;
base::flat_set<QString> _nameWords;
@ -116,6 +120,7 @@ private:
std::optional<int> _unreadCount;
rpl::event_stream<int> _unreadCountChanges;
int _unreadMutedCount = 0;
//bool _unreadMark = false;
};

View File

@ -1281,8 +1281,8 @@ void Session::applyPinnedDialogs(const QVector<MTPDialog> &list) {
if (const auto peer = peerFromMTP(data.vpeer)) {
setPinnedDialog(history(peer), true);
}
}, [&](const MTPDdialogFolder &data) { // #TODO archive
//setPinnedDialog(processFolder(data.vfolder), true);
}, [&](const MTPDdialogFolder &data) {
setPinnedDialog(processFolder(data.vfolder), true);
});
}
}
@ -1294,9 +1294,9 @@ void Session::applyPinnedDialogs(const QVector<MTPDialogPeer> &list) {
if (const auto peerId = peerFromMTP(data.vpeer)) {
setPinnedDialog(history(peerId), true);
}
}, [&](const MTPDdialogPeerFolder &data) { // #TODO archive
//const auto folderId = data.vfolder_id.v;
//setPinnedDialog(folder(folderId), true);
}, [&](const MTPDdialogPeerFolder &data) {
const auto folderId = data.vfolder_id.v;
setPinnedDialog(folder(folderId), true);
});
}
}
@ -2801,6 +2801,21 @@ Folder *Session::folderLoaded(FolderId id) {
const auto it = _folders.find(id);
return (it == end(_folders)) ? nullptr : it->second.get();
}
not_null<Folder*> Session::processFolder(const MTPFolder &data) {
return data.match([&](const MTPDfolder &data) {
return processFolder(data);
});
}
not_null<Folder*> Session::processFolder(const MTPDfolder &data) {
const auto result = folder(data.vid.v);
//if (data.has_photo()) {
// data.vphoto;
//}
//data.vtitle;
return result;
}
// // #feed
//void Session::setDefaultFeedId(FeedId id) {
// _defaultFeedId = id;

View File

@ -154,6 +154,7 @@ dialogsBotIconActive: icon {{ "dialogs_bot", dialogsChatIconFgActive, point(1px,
//dialogsFeedIcon: icon {{ "dialogs_feed", dialogsChatIconFg, point(4px, 4px) }}; // #feed
//dialogsFeedIconOver: icon {{ "dialogs_feed", dialogsChatIconFgOver, point(4px, 4px) }};
//dialogsFeedIconActive: icon {{ "dialogs_feed", dialogsChatIconFgActive, point(4px, 4px) }};
dialogsArchiveUserpic: icon {{ "archive_userpic", historyPeerUserpicFg }};
dialogsSendStateSkip: 20px;
dialogsSendingIcon: icon {{ "dialogs_sending", dialogsSendingIconFg, point(8px, 4px) }};

View File

@ -36,6 +36,9 @@ struct PositionChange {
class Entry {
public:
Entry(const Key &key);
Entry(const Entry &other) = delete;
Entry &operator=(const Entry &other) = delete;
virtual ~Entry() = default;
PositionChange adjustByPosInChatList(
Mode list,
@ -100,8 +103,6 @@ public:
return _timeId;
}
virtual ~Entry() = default;
mutable const HistoryItem *textCachedFor = nullptr; // cache
mutable Text lastItemTextCache;

View File

@ -108,11 +108,11 @@ DialogsInner::DialogsInner(QWidget *parent, not_null<Window::Controller*> contro
if (history->textCachedFor == item) {
history->updateChatListEntry();
}
//if (const auto folder = history->peer->folder()) { // #TODO archive
// if (folder->textCachedFor == item) {
// folder->updateChatListEntry();
// }
//}
if (const auto folder = history->folder()) {
if (folder->textCachedFor == item) {
folder->updateChatListEntry();
}
}
}, lifetime());
Auth().data().sendActionAnimationUpdated(
@ -1601,13 +1601,13 @@ void DialogsInner::contextMenuEvent(QContextMenuEvent *e) {
},
Window::PeerMenuSource::ChatsList);
} else if (const auto folder = row.key.folder()) {
//Window::FillFolderMenu( // #TODO archive
// _controller,
// folder,
// [&](const QString &text, Fn<void()> callback) {
// return _menu->addAction(text, std::move(callback));
// },
// Window::PeerMenuSource::ChatsList);
Window::FillFolderMenu(
_controller,
folder,
[&](const QString &text, Fn<void()> callback) {
return _menu->addAction(text, std::move(callback));
},
Window::PeerMenuSource::ChatsList);
}
connect(_menu.get(), &QObject::destroyed, [=] {
if (_menuRow.key) {
@ -1853,7 +1853,7 @@ void DialogsInner::dialogsReceived(const QVector<MTPDialog> &added) {
dialog.match([&](const MTPDdialog &data) {
applyDialog(data);
}, [&](const MTPDdialogFolder &data) {
//applyFolderDialog(data); // #TODO archive
applyFolderDialog(data);
});
}
refresh();
@ -1885,19 +1885,18 @@ void DialogsInner::applyDialog(const MTPDdialog &dialog) {
}
}
}
// #feed
//void DialogsInner::applyFeedDialog(const MTPDdialogFeed &dialog) {
// const auto feedId = dialog.vfeed_id.v;
// const auto feed = Auth().data().feed(feedId);
// feed->applyDialog(dialog);
//
// if (!feed->useProxyPromotion() && !feed->isPinnedDialog()) {
// const auto date = feed->chatListDate();
// if (!date.isNull()) {
// addSavedPeersAfter(date);
// }
// }
//}
void DialogsInner::applyFolderDialog(const MTPDdialogFolder &dialog) {
const auto folder = Auth().data().processFolder(dialog.vfolder);
folder->applyDialog(dialog);
if (!folder->useProxyPromotion() && !folder->isPinnedDialog()) {
const auto date = folder->chatListTimeId();
if (date != 0) {
addSavedPeersAfter(ParseDateTime(date));
}
}
}
void DialogsInner::addSavedPeersAfter(const QDateTime &date) {
auto &saved = cRefSavedPeersByTime();

View File

@ -202,7 +202,7 @@ private:
Dialogs::RowDescriptor chatListEntryLast() const;
void applyDialog(const MTPDdialog &dialog);
// void applyFeedDialog(const MTPDdialogFeed &dialog); // #feed
void applyFolderDialog(const MTPDdialogFolder &dialog);
void itemRemoved(not_null<const HistoryItem*> item);
enum class UpdateRowSection {

View File

@ -1603,7 +1603,7 @@ int History::unreadCount() const {
return _unreadCount ? *_unreadCount : 0;
}
int History::historiesUnreadCount() const {
int History::unreadCountForBadge() const {
const auto result = unreadCount();
return (!result && unreadMark()) ? 1 : result;
}
@ -1745,7 +1745,7 @@ bool History::changeMute(bool newMute) {
// }
//}
if (inChatList(Dialogs::Mode::All)) {
if (const auto count = historiesUnreadCount()) {
if (const auto count = unreadCountForBadge()) {
_owner->unreadMuteChanged(count, _mute);
const auto entriesWithUnreadDelta = 0;
@ -1807,6 +1807,32 @@ std::shared_ptr<AdminLog::LocalIdManager> History::adminLogIdManager() {
return result;
}
Data::Folder *History::folder() const {
return _folder;
}
void History::setFolder(not_null<Data::Folder*> folder) {
setFolderPointer(folder);
}
void History::clearFolder() {
setFolderPointer(nullptr);
}
void History::setFolderPointer(Data::Folder *folder) {
if (_folder != folder) {
const auto was = _folder;
_folder = folder;
if (was) {
was->unregisterOne(this);
}
if (_folder) {
_folder->registerOne(this);
}
updateChatListSortPosition();
}
}
TimeId History::adjustChatListTimeId() const {
const auto result = chatListTimeId();
if (const auto draft = cloudDraft()) {
@ -2369,7 +2395,7 @@ bool History::useProxyPromotion() const {
}
bool History::shouldBeInChatList() const {
if (peer->migrateTo()) {
if (peer->migrateTo() || folder() != nullptr) {
return false;
} else if (isPinnedDialog()) {
return true;
@ -3014,7 +3040,7 @@ void History::applyGroupAdminChanges(
void History::changedInChatListHook(Dialogs::Mode list, bool added) {
if (list == Dialogs::Mode::All) {
if (const auto delta = historiesUnreadCount() * (added ? 1 : -1)) {
if (const auto delta = unreadCountForBadge() * (added ? 1 : -1)) {
_owner->unreadIncrement(delta, mute());
const auto entriesDelta = added ? 1 : -1;

View File

@ -28,6 +28,7 @@ class AuthSession;
namespace Data {
struct Draft;
class Session;
class Folder;
} // namespace Data
namespace Dialogs {
@ -61,6 +62,7 @@ public:
History(not_null<Data::Session*> owner, PeerId peerId);
History(const History &) = delete;
History &operator=(const History &) = delete;
~History();
Data::Session &owner() const;
AuthSession &session() const;
@ -170,7 +172,7 @@ public:
void changeUnreadCount(int delta);
void setUnreadMark(bool unread);
bool unreadMark() const;
int historiesUnreadCount() const; // unreadCount || unreadMark ? 1 : 0.
int unreadCountForBadge() const; // unreadCount || unreadMark ? 1 : 0.
bool mute() const;
bool changeMute(bool newMute);
void addUnreadBar();
@ -324,7 +326,9 @@ public:
std::shared_ptr<AdminLog::LocalIdManager> adminLogIdManager();
virtual ~History();
Data::Folder *folder() const;
void setFolder(not_null<Data::Folder*> folder);
void clearFolder();
// Still public data.
std::deque<std::unique_ptr<HistoryBlock>> blocks;
@ -461,6 +465,8 @@ private:
void createLocalDraftFromCloud();
void setFolderPointer(Data::Folder *folder);
not_null<Data::Session*> _owner;
Flags _flags = 0;
bool _mute = false;
@ -472,6 +478,8 @@ private:
bool _loadedAtTop = false;
bool _loadedAtBottom = true;
Data::Folder *_folder = nullptr;
std::optional<MsgId> _inboxReadBefore;
std::optional<MsgId> _outboxReadBefore;
std::optional<int> _unreadCount;

View File

@ -4014,6 +4014,12 @@ void MainWidget::feedUpdate(const MTPUpdate &update) {
});
} break;
case mtpc_updateFolderPeers: {
const auto &data = update.c_updateFolderPeers();
ptsUpdateAndApply(data.vpts.v, data.vpts_count.v, update);
} break;
// Deleted messages.
case mtpc_updateDeleteMessages: {
auto &d = update.c_updateDeleteMessages();
@ -4287,8 +4293,7 @@ void MainWidget::feedUpdate(const MTPUpdate &update) {
return !session().data().historyLoaded(
peerFromMTP(data.vpeer));
}, [&](const MTPDdialogPeerFolder &data) {
//return !session().data().folderLoaded(data.vfolder_id.v);
return true; // #TODO archive
return !session().data().folderLoaded(data.vfolder_id.v);
});
};
const auto allLoaded = ranges::find_if(order, notLoaded)
@ -4317,17 +4322,16 @@ void MainWidget::feedUpdate(const MTPUpdate &update) {
_dialogs->loadPinnedDialogs();
}
}, [&](const MTPDdialogPeerFolder &data) {
// #TODO archive
//const auto id = data.vfolder_id.v;
//if (const auto folder = session().data().folderLoaded(id)) {
// session().data().setPinnedDialog(folder, d.is_pinned());
//} else {
// DEBUG_LOG(("API Error: "
// "pinned folder not loaded for feedId %1"
// ).arg(folderId
// ));
// _dialogs->loadPinnedDialogs();
//}
const auto id = data.vfolder_id.v;
if (const auto folder = session().data().folderLoaded(id)) {
session().data().setPinnedDialog(folder, d.is_pinned());
} else {
DEBUG_LOG(("API Error: "
"pinned folder not loaded for folderId %1"
).arg(id
));
_dialogs->loadPinnedDialogs();
}
});
} break;