From 724fe65d72518316429efbfc51ac6cda973e1a45 Mon Sep 17 00:00:00 2001 From: John Preston Date: Thu, 4 Jan 2018 12:40:58 +0300 Subject: [PATCH] Start feeds support. --- Telegram/SourceFiles/app.cpp | 5 +++ Telegram/SourceFiles/auth_session.cpp | 16 ++++++++ Telegram/SourceFiles/auth_session.h | 9 +++++ Telegram/SourceFiles/boxes/share_box.cpp | 19 ++++++---- Telegram/SourceFiles/data/data_feed.cpp | 28 ++++++++++++++ Telegram/SourceFiles/data/data_feed.h | 32 ++++++++++++++++ Telegram/SourceFiles/data/data_peer.cpp | 21 ++++++++++ Telegram/SourceFiles/data/data_peer.h | 38 +++++++++++++++---- Telegram/SourceFiles/data/data_types.h | 1 + .../dialogs/dialogs_indexed_list.cpp | 16 +++++--- .../dialogs/dialogs_indexed_list.h | 4 +- .../dialogs/dialogs_inner_widget.cpp | 23 ++++++++++- Telegram/SourceFiles/dialogs/dialogs_list.cpp | 13 ++++--- Telegram/SourceFiles/dialogs/dialogs_list.h | 4 +- Telegram/gyp/telegram_sources.txt | 2 + 15 files changed, 199 insertions(+), 32 deletions(-) create mode 100644 Telegram/SourceFiles/data/data_feed.cpp create mode 100644 Telegram/SourceFiles/data/data_feed.h diff --git a/Telegram/SourceFiles/app.cpp b/Telegram/SourceFiles/app.cpp index a4ac78929..22c1f30f2 100644 --- a/Telegram/SourceFiles/app.cpp +++ b/Telegram/SourceFiles/app.cpp @@ -582,6 +582,11 @@ namespace { cdata->setRestrictionReason(QString()); } cdata->setFlags(d.vflags.v); + if (d.has_feed_id()) { + cdata->setFeed(Auth().data().feed(d.vfeed_id.v)); + } else { + cdata->clearFeed(); + } } QString uname = d.has_username() ? TextUtilities::SingleLine(qs(d.vusername)) : QString(); diff --git a/Telegram/SourceFiles/auth_session.cpp b/Telegram/SourceFiles/auth_session.cpp index 928c3048e..c778bed4b 100644 --- a/Telegram/SourceFiles/auth_session.cpp +++ b/Telegram/SourceFiles/auth_session.cpp @@ -15,6 +15,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "storage/localstorage.h" #include "storage/storage_facade.h" #include "storage/serialize_common.h" +#include "data/data_feed.h" #include "history/history_item_components.h" #include "window/notifications_manager.h" #include "window/themes/window_theme.h" @@ -408,6 +409,21 @@ MessageIdsList AuthSessionData::groupToIds( return result; } +not_null AuthSessionData::feed(FeedId id) { + if (const auto result = feedLoaded(id)) { + return result; + } + const auto [it, ok] = _feeds.emplace( + id, + std::make_unique(id)); + return it->second.get(); +} + +Data::Feed *AuthSessionData::feedLoaded(FeedId id) { + const auto it = _feeds.find(id); + return (it == _feeds.end()) ? nullptr : it->second.get(); +} + AuthSession &Auth() { auto result = Messenger::Instance().authSession(); Assert(result != nullptr); diff --git a/Telegram/SourceFiles/auth_session.h b/Telegram/SourceFiles/auth_session.h index 0b78a1456..f472c1b63 100644 --- a/Telegram/SourceFiles/auth_session.h +++ b/Telegram/SourceFiles/auth_session.h @@ -16,6 +16,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL class ApiWrap; enum class SendFilesWay; +namespace Data { +class Feed; +} // namespace Data + namespace Storage { class Downloader; class Uploader; @@ -266,6 +270,9 @@ public: MessageIdsList itemsToIds(const HistoryItemsList &items) const; MessageIdsList groupToIds(not_null group) const; + not_null feed(FeedId id); + Data::Feed *feedLoaded(FeedId id); + private: struct Variables { Variables(); @@ -325,6 +332,8 @@ private: Stickers::Order _archivedStickerSetsOrder; Stickers::SavedGifs _savedGifs; + base::flat_map> _feeds; + rpl::event_stream _thirdSectionInfoEnabledValue; bool _tabbedReplacedWithInfo = false; rpl::event_stream _tabbedReplacedWithInfoValue; diff --git a/Telegram/SourceFiles/boxes/share_box.cpp b/Telegram/SourceFiles/boxes/share_box.cpp index 26cb04bf2..75065716e 100644 --- a/Telegram/SourceFiles/boxes/share_box.cpp +++ b/Telegram/SourceFiles/boxes/share_box.cpp @@ -273,16 +273,18 @@ ShareBox::Inner::Inner(QWidget *parent, ShareBox::FilterCallback &&filterCallbac _rowHeight = st::shareRowHeight; setAttribute(Qt::WA_OpaquePaintEvent); - auto dialogs = App::main()->dialogsList(); - if (auto self = App::self()) { + const auto dialogs = App::main()->dialogsList(); + if (const auto self = App::self()) { if (_filterCallback(App::self())) { _chatsIndexed->addToEnd(App::history(self)); } } - for_const (auto row, dialogs->all()) { - auto history = row->history(); - if (!history->peer->isSelf() && _filterCallback(history->peer)) { - _chatsIndexed->addToEnd(history); + for (const auto row : dialogs->all()) { + // #TODO dialogs + if (const auto history = row->history()) { + if (!history->peer->isSelf() && _filterCallback(history->peer)) { + _chatsIndexed->addToEnd(history); + } } } @@ -640,8 +642,9 @@ void ShareBox::Inner::changeCheckState(Chat *chat) { if (!_filter.isEmpty()) { auto row = _chatsIndexed->getRow(chat->peer->id); if (!row) { - auto rowsByLetter = _chatsIndexed->addToEnd(App::history(chat->peer)); - auto it = rowsByLetter.find(0); + const auto rowsByLetter = _chatsIndexed->addToEnd( + App::history(chat->peer)); + const auto it = rowsByLetter.find(0); Assert(it != rowsByLetter.cend()); row = it->second; } diff --git a/Telegram/SourceFiles/data/data_feed.cpp b/Telegram/SourceFiles/data/data_feed.cpp new file mode 100644 index 000000000..6ac8b3e01 --- /dev/null +++ b/Telegram/SourceFiles/data/data_feed.cpp @@ -0,0 +1,28 @@ +/* +This file is part of Telegram Desktop, +the official desktop application for the Telegram messaging service. + +For license and copyright information please follow this link: +https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL +*/ +#include "data/data_feed.h" + +namespace Data { + +Feed::Feed(FeedId id) : _id(id) { +} + +void Feed::registerOne(not_null channel) { + _channels.emplace(channel); +} + +void Feed::unregisterOne(not_null channel) { + _channels.remove(channel); +} + +void Feed::setUnreadCounts(int unreadCount, int unreadMutedCount) { + _unreadCount = unreadCount; + _unreadMutedCount = unreadMutedCount; +} + +} // namespace Data diff --git a/Telegram/SourceFiles/data/data_feed.h b/Telegram/SourceFiles/data/data_feed.h new file mode 100644 index 000000000..78722c88d --- /dev/null +++ b/Telegram/SourceFiles/data/data_feed.h @@ -0,0 +1,32 @@ +/* +This file is part of Telegram Desktop, +the official desktop application for the Telegram messaging service. + +For license and copyright information please follow this link: +https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL +*/ +#pragma once + +class ChannelData; + +namespace Data { + +class Feed { +public: + Feed(FeedId id); + + void registerOne(not_null channel); + void unregisterOne(not_null channel); + + void setUnreadCounts(int unreadCount, int unreadMutedCount); + +private: + FeedId _id = 0; + base::flat_set> _channels; + int _unreadCount = 0; + int _unreadMutedCount = 0; + bool _complete = false; + +}; + +} // namespace Data diff --git a/Telegram/SourceFiles/data/data_peer.cpp b/Telegram/SourceFiles/data/data_peer.cpp index a0546747a..56a37d489 100644 --- a/Telegram/SourceFiles/data/data_peer.cpp +++ b/Telegram/SourceFiles/data/data_peer.cpp @@ -12,6 +12,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "data/data_peer_values.h" #include "data/data_channel_admins.h" #include "data/data_photo.h" +#include "data/data_feed.h" #include "lang/lang_keys.h" #include "observer_peer.h" #include "mainwidget.h" @@ -849,6 +850,26 @@ void ChannelData::setPinnedMessageId(MsgId messageId) { } } +void ChannelData::setFeed(not_null feed) { + setFeedPointer(feed); +} + +void ChannelData::clearFeed() { + setFeedPointer(nullptr); +} + +void ChannelData::setFeedPointer(Data::Feed *feed) { + if (_feed != feed) { + if (_feed) { + _feed->unregisterOne(this); + } + _feed = feed; + if (_feed) { + _feed->registerOne(this); + } + } +} + bool ChannelData::canBanMembers() const { return (adminRights() & AdminRight::f_ban_users) || amCreator(); diff --git a/Telegram/SourceFiles/data/data_peer.h b/Telegram/SourceFiles/data/data_peer.h index d17a8d13a..6b94a2fb7 100644 --- a/Telegram/SourceFiles/data/data_peer.h +++ b/Telegram/SourceFiles/data/data_peer.h @@ -22,6 +22,8 @@ class ChannelData; namespace Data { +class Feed; + int PeerColorIndex(PeerId peerId); int PeerColorIndex(int32 bareId); style::color PeerUserpicColor(PeerId peerId); @@ -103,6 +105,7 @@ public: ChatData *migrateFrom() const; ChannelData *migrateTo() const; + Data::Feed *feed() const; void updateFull(); void updateFullForced(); @@ -1009,11 +1012,19 @@ public: setPinnedMessageId(0); } + void setFeed(not_null feed); + void clearFeed(); + + Data::Feed *feed() const { + return _feed; + } + private: void flagsUpdated(MTPDchannel::Flags diff); void fullFlagsUpdated(MTPDchannelFull::Flags diff); bool canEditLastAdmin(not_null user) const; + void setFeedPointer(Data::Feed *feed); Flags _flags = Flags(MTPDchannel_ClientFlag::f_forbidden | 0); FullFlags _fullFlags; @@ -1035,6 +1046,7 @@ private: QString _about; QString _inviteLink; + Data::Feed *_feed = nullptr; rpl::lifetime _lifetime; @@ -1105,16 +1117,26 @@ inline bool isMegagroup(const PeerData *peer) { return peer ? peer->isMegagroup() : false; } inline ChatData *PeerData::migrateFrom() const { - return (isMegagroup() && asChannel()->amIn()) - ? asChannel()->mgInfo->migrateFromPtr - : nullptr; + if (const auto megagroup = asMegagroup()) { + return megagroup->amIn() + ? megagroup->mgInfo->migrateFromPtr + : nullptr; + } + return nullptr; } inline ChannelData *PeerData::migrateTo() const { - return (isChat() - && asChat()->migrateToPtr - && asChat()->migrateToPtr->amIn()) - ? asChat()->migrateToPtr - : nullptr; + if (const auto chat = asChat()) { + if (const auto migrateTo = chat->migrateToPtr) { + return migrateTo->amIn() ? migrateTo : nullptr; + } + } + return nullptr; +} +inline Data::Feed *PeerData::feed() const { + if (const auto channel = asChannel()) { + return channel->feed(); + } + return nullptr; } inline const Text &PeerData::dialogName() const { return migrateTo() diff --git a/Telegram/SourceFiles/data/data_types.h b/Telegram/SourceFiles/data/data_types.h index 5a0901c9b..c6fd50f3f 100644 --- a/Telegram/SourceFiles/data/data_types.h +++ b/Telegram/SourceFiles/data/data_types.h @@ -27,6 +27,7 @@ class ChannelData; using UserId = int32; using ChatId = int32; using ChannelId = int32; +using FeedId = int32; constexpr auto NoChannel = ChannelId(0); diff --git a/Telegram/SourceFiles/dialogs/dialogs_indexed_list.cpp b/Telegram/SourceFiles/dialogs/dialogs_indexed_list.cpp index 7560e93bc..a82f2abb8 100644 --- a/Telegram/SourceFiles/dialogs/dialogs_indexed_list.cpp +++ b/Telegram/SourceFiles/dialogs/dialogs_indexed_list.cpp @@ -15,7 +15,7 @@ IndexedList::IndexedList(SortMode sortMode) , _empty(sortMode) { } -RowsByLetter IndexedList::addToEnd(History *history) { +RowsByLetter IndexedList::addToEnd(not_null history) { RowsByLetter result; if (!_list.contains(history->peer->id)) { result.emplace(0, _list.addToEnd(history)); @@ -32,8 +32,8 @@ RowsByLetter IndexedList::addToEnd(History *history) { return result; } -Row *IndexedList::addByName(History *history) { - if (auto row = _list.getRow(history->peer->id)) { +Row *IndexedList::addByName(not_null history) { + if (const auto row = _list.getRow(history->peer->id)) { return row; } @@ -105,11 +105,14 @@ void IndexedList::peerNameChanged(Mode list, not_null peer, const Pee adjustNames(list, peer, oldChars); } -void IndexedList::adjustByName(not_null peer, const PeerData::NameFirstChars &oldChars) { - Row *mainRow = _list.adjustByName(peer); +void IndexedList::adjustByName( + not_null peer, + const PeerData::NameFirstChars &oldChars) { + const auto mainRow = _list.adjustByName(peer); if (!mainRow) return; - History *history = mainRow->history(); + // #TODO dialogs + const auto history = mainRow->history(); PeerData::NameFirstChars toRemove = oldChars, toAdd; for (auto ch : peer->nameFirstChars()) { @@ -145,6 +148,7 @@ void IndexedList::adjustNames(Mode list, not_null peer, const PeerDat auto mainRow = _list.getRow(peer->id); if (!mainRow) return; + // #TODO dialogs auto history = mainRow->history(); PeerData::NameFirstChars toRemove = oldChars, toAdd; diff --git a/Telegram/SourceFiles/dialogs/dialogs_indexed_list.h b/Telegram/SourceFiles/dialogs/dialogs_indexed_list.h index 299374db1..3b3d344df 100644 --- a/Telegram/SourceFiles/dialogs/dialogs_indexed_list.h +++ b/Telegram/SourceFiles/dialogs/dialogs_indexed_list.h @@ -18,8 +18,8 @@ class IndexedList { public: IndexedList(SortMode sortMode); - RowsByLetter addToEnd(History *history); - Row *addByName(History *history); + RowsByLetter addToEnd(not_null history); + Row *addByName(not_null history); void adjustByPos(const RowsByLetter &links); void moveToTop(not_null peer); diff --git a/Telegram/SourceFiles/dialogs/dialogs_inner_widget.cpp b/Telegram/SourceFiles/dialogs/dialogs_inner_widget.cpp index 379263a3b..8c5fec342 100644 --- a/Telegram/SourceFiles/dialogs/dialogs_inner_widget.cpp +++ b/Telegram/SourceFiles/dialogs/dialogs_inner_widget.cpp @@ -17,6 +17,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "ui/widgets/popup_menu.h" #include "ui/text_options.h" #include "data/data_drafts.h" +#include "data/data_feed.h" #include "lang/lang_keys.h" #include "mainwindow.h" #include "mainwidget.h" @@ -1561,7 +1562,27 @@ void DialogsInner::applyDialog(const MTPDdialog &dialog) { } void DialogsInner::applyFeedDialog(const MTPDdialogFeed &dialog) { - // #TODO feeds + const auto peerId = peerFromMTP(dialog.vpeer); + const auto feedId = dialog.vfeed_id.v; + const auto feed = Auth().data().feed(feedId); + const auto addChannel = [&](ChannelId channelId) { + if (const auto channel = App::channelLoaded(channelId)) { + channel->setFeed(feed); + } + }; + if (peerId && peerIsChannel(peerId)) { + addChannel(peerToChannel(peerId)); + } + for (const auto &channelId : dialog.vfeed_other_channels.v) { + addChannel(channelId.v); + } + feed->setUnreadCounts( + dialog.vunread_count.v, + dialog.vunread_muted_count.v); + if (dialog.has_read_max_position()) { + // #TODO feeds +// feed->set + } } void DialogsInner::addSavedPeersAfter(const QDateTime &date) { diff --git a/Telegram/SourceFiles/dialogs/dialogs_list.cpp b/Telegram/SourceFiles/dialogs/dialogs_list.cpp index 8b45dcdbc..b1c05f041 100644 --- a/Telegram/SourceFiles/dialogs/dialogs_list.cpp +++ b/Telegram/SourceFiles/dialogs/dialogs_list.cpp @@ -33,8 +33,8 @@ void List::adjustCurrent(int32 y, int32 h) const { } } -Row *List::addToEnd(History *history) { - Row *result = new Row(history, _end->_prev, _end, _end->_pos); +Row *List::addToEnd(not_null history) { + const auto result = new Row(history, _end->_prev, _end, _end->_pos); _end->_pos++; if (_begin == _end) { _begin = _current = result; @@ -121,10 +121,13 @@ Row *List::adjustByName(const PeerData *peer) { return row; } -Row *List::addByName(History *history) { - if (_sortMode != SortMode::Name) return nullptr; +Row *List::addByName(not_null history) { + if (_sortMode != SortMode::Name) { + return nullptr; + } - Row *row = addToEnd(history), *change = row; + const auto row = addToEnd(history); + auto change = row; const QString &peerName(history->peer->name); while (change->_prev && change->_prev->history()->peer->name.compare(peerName, Qt::CaseInsensitive) > 0) { change = change->_prev; diff --git a/Telegram/SourceFiles/dialogs/dialogs_list.h b/Telegram/SourceFiles/dialogs/dialogs_list.h index 74d305ddb..fa3698062 100644 --- a/Telegram/SourceFiles/dialogs/dialogs_list.h +++ b/Telegram/SourceFiles/dialogs/dialogs_list.h @@ -38,9 +38,9 @@ public: return *i; } - Row *addToEnd(History *history); + Row *addToEnd(not_null history); Row *adjustByName(const PeerData *peer); - Row *addByName(History *history); + Row *addByName(not_null history); bool moveToTop(PeerId peerId); void adjustByPos(Row *row); bool del(PeerId peerId, Row *replacedBy = nullptr); diff --git a/Telegram/gyp/telegram_sources.txt b/Telegram/gyp/telegram_sources.txt index 11b5c6ff6..6ea1aa201 100644 --- a/Telegram/gyp/telegram_sources.txt +++ b/Telegram/gyp/telegram_sources.txt @@ -167,6 +167,8 @@ <(src_loc)/data/data_document.h <(src_loc)/data/data_drafts.cpp <(src_loc)/data/data_drafts.h +<(src_loc)/data/data_feed.cpp +<(src_loc)/data/data_feed.h <(src_loc)/data/data_flags.h <(src_loc)/data/data_game.h <(src_loc)/data/data_notify_settings.cpp