Request full feed channels list before messages.

This commit is contained in:
John Preston 2018-01-30 15:13:46 +03:00
parent 20889d7003
commit 280ddb4629
7 changed files with 169 additions and 18 deletions

View file

@ -2637,12 +2637,81 @@ void ApiWrap::userPhotosDone(
));
}
void ApiWrap::requestFeedChannels(not_null<Data::Feed*> feed) {
if (_feedChannelsRequests.contains(feed)) {
return;
}
const auto hash = feed->channelsHash();
request(MTPchannels_GetFeedSources(
MTP_flags(MTPchannels_GetFeedSources::Flag::f_feed_id),
MTP_int(feed->id()),
MTP_int(hash)
)).done([=](const MTPchannels_FeedSources &result) {
_feedChannelsRequests.remove(feed);
switch (result.type()) {
case mtpc_channels_feedSourcesNotModified:
if (feed->channelsHash() == hash) {
feedChannelsDone(feed);
} else {
requestFeedChannels(feed);
}
break;
case mtpc_channels_feedSources: {
const auto &data = result.c_channels_feedSources();
App::feedUsers(data.vusers);
App::feedChats(data.vchats);
for (const auto &broadcasts : data.vfeeds.v) {
if (broadcasts.type() == mtpc_feedBroadcasts) {
const auto &list = broadcasts.c_feedBroadcasts();
const auto feedId = list.vfeed_id.v;
const auto feed = _session->data().feed(feedId);
auto channels = std::vector<not_null<ChannelData*>>();
for (const auto &channelId : list.vchannels.v) {
channels.push_back(App::channel(channelId.v));
}
feed->setChannels(std::move(channels));
}
}
if (feed->channelsLoaded()) {
feedChannelsDone(feed);
} else {
LOG(("API Error: feed channels not received for "
).arg(feed->id()));
}
} break;
default: Unexpected("Type in channels.getFeedSources response.");
}
}).fail([=](const RPCError &error) {
_feedChannelsRequests.remove(feed);
}).send();
_feedChannelsRequests.emplace(feed);
}
void ApiWrap::feedChannelsDone(not_null<Data::Feed*> feed) {
feed->setChannelsLoaded(true);
for (const auto key : base::take(_feedMessagesRequestsPending)) {
std::apply(
[=](auto&&...args) { requestFeedMessages(args...); },
key);
}
}
void ApiWrap::requestFeedMessages(
not_null<Data::Feed*> feed,
Data::MessagePosition messageId,
SliceType slice) {
const auto key = std::make_tuple(feed, messageId, slice);
if (_feedMessagesRequests.contains(key)) {
if (_feedMessagesRequests.contains(key)
|| _feedMessagesRequestsPending.contains(key)) {
return;
}
if (!feed->channelsLoaded()) {
_feedMessagesRequestsPending.emplace(key);
requestFeedChannels(feed);
return;
}
@ -2656,7 +2725,7 @@ void ApiWrap::requestFeedMessages(
}
Unexpected("Direction in PrepareSearchRequest");
}();
const auto sourcesHash = int32(0);// feed->channelsHash(); // #TODO
const auto sourcesHash = feed->channelsHash();
const auto hash = int32(0);
const auto flags = (messageId && messageId.fullId.channel)
? MTPchannels_GetFeed::Flag::f_offset_position
@ -2681,7 +2750,7 @@ void ApiWrap::requestFeedMessages(
}).fail([=](const RPCError &error) {
_feedMessagesRequests.remove(key);
}).send();
_feedMessagesRequests.emplace(key, requestId);
_feedMessagesRequests.emplace(key);
}
void ApiWrap::feedMessagesDone(

View file

@ -161,6 +161,8 @@ public:
not_null<UserData*> user,
PhotoId afterId);
void requestFeedChannels(
not_null<Data::Feed*> feed);
void requestFeedMessages(
not_null<Data::Feed*> feed,
Data::MessagePosition messageId,
@ -323,6 +325,7 @@ private:
PhotoId photoId,
const MTPphotos_Photos &result);
void feedChannelsDone(not_null<Data::Feed*> feed);
void feedMessagesDone(
not_null<Data::Feed*> feed,
Data::MessagePosition messageId,
@ -450,10 +453,15 @@ private:
base::flat_map<not_null<UserData*>, mtpRequestId> _userPhotosRequests;
base::flat_map<std::tuple<
base::flat_set<not_null<Data::Feed*>> _feedChannelsRequests;
base::flat_set<std::tuple<
not_null<Data::Feed*>,
Data::MessagePosition,
SliceType>, mtpRequestId> _feedMessagesRequests;
SliceType>> _feedMessagesRequests;
base::flat_set<std::tuple<
not_null<Data::Feed*>,
Data::MessagePosition,
SliceType>> _feedMessagesRequestsPending;
rpl::event_stream<SendOptions> _sendActions;

View file

@ -162,6 +162,49 @@ int32 Feed::channelsHash() const {
}));
}
bool Feed::channelsLoaded() const {
return _channelsLoaded;
}
void Feed::setChannelsLoaded(bool loaded) {
_channelsLoaded = loaded;
}
void Feed::setChannels(std::vector<not_null<ChannelData*>> channels) {
const auto remove = ranges::view::all(
_channels
) | ranges::view::transform([](not_null<History*> history) {
return history->peer->asChannel();
}) | ranges::view::filter([&](not_null<ChannelData*> channel) {
return !base::contains(channels, channel);
}) | ranges::to_vector;
const auto add = ranges::view::all(
channels
) | ranges::view::filter([&](not_null<ChannelData*> channel) {
return ranges::find(
_channels,
channel.get(),
[](auto history) { return history->peer->asChannel(); }
) != end(_channels);
}) | ranges::to_vector;
for (const auto channel : remove) {
channel->clearFeed();
}
for (const auto channel : add) {
channel->setFeed(this);
}
_channels.clear();
for (const auto channel : channels) {
Assert(channel->feed() == this);
_channels.push_back(App::history(channel));
}
_channelsLoaded = true;
}
bool Feed::justSetLastMessage(not_null<HistoryItem*> item) {
if (_lastMessage && item->position() <= _lastMessage->position()) {
return false;

View file

@ -66,6 +66,9 @@ public:
const std::vector<not_null<History*>> &channels() const;
int32 channelsHash() const;
bool channelsLoaded() const;
void setChannelsLoaded(bool loaded);
void setChannels(std::vector<not_null<ChannelData*>> channels);
private:
void indexNameParts();
@ -75,6 +78,7 @@ private:
FeedId _id = 0;
not_null<Data::Session*> _parent;
std::vector<not_null<History*>> _channels;
bool _channelsLoaded = false;
QString _name;
base::flat_set<QString> _nameWords;

View file

@ -185,23 +185,39 @@ void paintRow(
icon.paint(p, fullWidth - st::dialogsPadding.x() - icon.width(), texttop, fullWidth);
availableWidth -= icon.width() + st::dialogsUnreadPadding;
}
auto sendStateIcon = ([draft, item, active, selected]() -> const style::icon* {
auto sendStateIcon = [&]() -> const style::icon* {
if (draft) {
if (draft->saveRequestId) {
return &(active ? st::dialogsSendingIconActive : (selected ? st::dialogsSendingIconOver : st::dialogsSendingIcon));
return &(active
? st::dialogsSendingIconActive
: (selected
? st::dialogsSendingIconOver
: st::dialogsSendingIcon));
}
} else if (item && !item->isEmpty() && item->needCheck()) {
if (item->id > 0) {
if (item->unread()) {
return &(active ? st::dialogsSentIconActive : (selected ? st::dialogsSentIconOver : st::dialogsSentIcon));
return &(active
? st::dialogsSentIconActive
: (selected
? st::dialogsSentIconOver
: st::dialogsSentIcon));
}
return &(active ? st::dialogsReceivedIconActive : (selected ? st::dialogsReceivedIconOver : st::dialogsReceivedIcon));
return &(active
? st::dialogsReceivedIconActive
: (selected
? st::dialogsReceivedIconOver
: st::dialogsReceivedIcon));
}
return &(active ? st::dialogsSendingIconActive : (selected ? st::dialogsSendingIconOver : st::dialogsSendingIcon));
return &(active
? st::dialogsSendingIconActive
: (selected
? st::dialogsSendingIconOver
: st::dialogsSendingIcon));
}
return nullptr;
})();
if (sendStateIcon) {
}();
if (sendStateIcon && history) {
rectForName.setWidth(rectForName.width() - st::dialogsSendStateSkip);
sendStateIcon->paint(p, rectForName.topLeft() + QPoint(rectForName.width(), 0), fullWidth);
}

View file

@ -236,6 +236,7 @@ ListWidget::ListWidget(
, _delegate(delegate)
, _controller(controller)
, _context(_delegate->listContext())
, _itemAverageHeight(itemMinimalHeight())
, _scrollDateCheck([this] { scrollDateCheck(); })
, _selectEnabled(_delegate->listAllowsMultiSelect()) {
setMouseTracking(true);
@ -782,6 +783,12 @@ void ListWidget::setTextSelection(
}
}
int ListWidget::itemMinimalHeight() const {
return st::msgMarginTopAttached
+ st::msgPhotoSize
+ st::msgMargin.bottom();
}
void ListWidget::checkMoveToOtherViewer() {
auto visibleHeight = (_visibleBottom - _visibleTop);
if (width() <= 0
@ -795,13 +802,10 @@ void ListWidget::checkMoveToOtherViewer() {
auto topItem = findItemByY(_visibleTop);
auto bottomItem = findItemByY(_visibleBottom);
auto preloadedHeight = kPreloadedScreensCountFull * visibleHeight;
auto minItemHeight = st::msgMarginTopAttached
+ st::msgPhotoSize
+ st::msgMargin.bottom();
auto preloadedCount = preloadedHeight / minItemHeight;
auto preloadedCount = preloadedHeight / _itemAverageHeight;
auto preloadIdsLimitMin = (preloadedCount / 2) + 1;
auto preloadIdsLimit = preloadIdsLimitMin
+ (visibleHeight / minItemHeight);
+ (visibleHeight / _itemAverageHeight);
auto preloadBefore = kPreloadIfLessThanScreens * visibleHeight;
auto before = _slice.skippedBefore;
@ -814,7 +818,7 @@ void ListWidget::checkMoveToOtherViewer() {
auto minScreenDelta = kPreloadedScreensCount
- kPreloadIfLessThanScreens;
auto minUniversalIdDelta = (minScreenDelta * visibleHeight)
/ minItemHeight;
/ _itemAverageHeight;
auto preloadAroundMessage = [&](not_null<Element*> view) {
auto preloadRequired = false;
auto itemPosition = view->data()->position();
@ -952,6 +956,11 @@ int ListWidget::resizeGetHeight(int newWidth) {
newHeight += view->height();
}
}
if (newHeight > 0) {
_itemAverageHeight = std::max(
itemMinimalHeight(),
newHeight / int(_items.size()));
}
_itemsWidth = newWidth;
_itemsHeight = newHeight;
_itemsTop = (_minHeight > _itemsHeight + st::historyPaddingBottom) ? (_minHeight - _itemsHeight - st::historyPaddingBottom) : 0;

View file

@ -295,6 +295,7 @@ private:
void setTextSelection(
not_null<Element*> view,
TextSelection selection);
int itemMinimalHeight() const;
bool isGoodForSelection(not_null<HistoryItem*> item) const;
bool isGoodForSelection(
@ -393,6 +394,7 @@ private:
int _itemsTop = 0;
int _itemsWidth = 0;
int _itemsHeight = 0;
int _itemAverageHeight = 0;
int _minHeight = 0;
int _visibleTop = 0;