mirror of
https://github.com/vale981/tdesktop
synced 2025-03-06 02:01:40 -05:00
Request full feed channels list before messages.
This commit is contained in:
parent
20889d7003
commit
280ddb4629
7 changed files with 169 additions and 18 deletions
|
@ -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(
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Add table
Reference in a new issue