mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-04-16 14:17:12 +02:00
Added support of posts_between flag for sponsored messages.
This commit is contained in:
parent
fb33951c94
commit
26f287fae0
8 changed files with 173 additions and 14 deletions
|
@ -10,11 +10,13 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "api/api_text_entities.h"
|
||||
#include "apiwrap.h"
|
||||
#include "base/unixtime.h"
|
||||
#include "data/data_user.h"
|
||||
#include "data/data_channel.h"
|
||||
#include "data/data_peer_id.h"
|
||||
#include "data/data_session.h"
|
||||
#include "data/data_user.h"
|
||||
#include "history/history.h"
|
||||
#include "history/history_message.h"
|
||||
#include "history/view/history_view_element.h"
|
||||
#include "main/main_session.h"
|
||||
#include "ui/image/image_location_factory.h"
|
||||
|
||||
|
@ -61,7 +63,9 @@ bool SponsoredMessages::append(not_null<History*> history) {
|
|||
return false;
|
||||
}
|
||||
auto &list = it->second;
|
||||
if (list.showedAll || !TooEarlyForRequest(list.received)) {
|
||||
if (list.showedAll
|
||||
|| !TooEarlyForRequest(list.received)
|
||||
|| list.postsBetween) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -81,11 +85,98 @@ bool SponsoredMessages::append(not_null<History*> history) {
|
|||
return true;
|
||||
}
|
||||
|
||||
void SponsoredMessages::inject(
|
||||
not_null<History*> history,
|
||||
MsgId injectAfterMsgId,
|
||||
int betweenHeight,
|
||||
int fallbackWidth) {
|
||||
if (!canHaveFor(history)) {
|
||||
return;
|
||||
}
|
||||
const auto it = _data.find(history);
|
||||
if (it == end(_data)) {
|
||||
return;
|
||||
}
|
||||
auto &list = it->second;
|
||||
if (!list.postsBetween || (list.entries.size() == list.injectedCount)) {
|
||||
return;
|
||||
}
|
||||
|
||||
while (true) {
|
||||
const auto entryIt = ranges::find_if(list.entries, [](const auto &e) {
|
||||
return e.item == nullptr;
|
||||
});
|
||||
if (entryIt == end(list.entries)) {
|
||||
list.showedAll = true;
|
||||
return;
|
||||
}
|
||||
const auto lastView = (entryIt != begin(list.entries))
|
||||
? (entryIt - 1)->item->mainView()
|
||||
: (injectAfterMsgId == ShowAtUnreadMsgId)
|
||||
? history->firstUnreadMessage()
|
||||
: [&] {
|
||||
const auto message = history->peer->owner().message(
|
||||
history->peer->id,
|
||||
injectAfterMsgId);
|
||||
return message ? message->mainView() : nullptr;
|
||||
}();
|
||||
if (!lastView || !lastView->block()) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto summaryBetween = 0;
|
||||
auto summaryHeight = 0;
|
||||
|
||||
using BlockPtr = std::unique_ptr<HistoryBlock>;
|
||||
using ViewPtr = std::unique_ptr<HistoryView::Element>;
|
||||
auto blockIt = ranges::find(
|
||||
history->blocks,
|
||||
lastView->block(),
|
||||
&BlockPtr::get);
|
||||
if (blockIt == end(history->blocks)) {
|
||||
return;
|
||||
}
|
||||
const auto messages = [&]() -> const std::vector<ViewPtr> & {
|
||||
return (*blockIt)->messages;
|
||||
};
|
||||
auto lastViewIt = ranges::find(messages(), lastView, &ViewPtr::get);
|
||||
while ((summaryBetween < list.postsBetween)
|
||||
|| (summaryHeight < betweenHeight)) {
|
||||
lastViewIt++;
|
||||
if (lastViewIt == end(messages())) {
|
||||
blockIt++;
|
||||
if (blockIt != end(history->blocks)) {
|
||||
lastViewIt = begin(messages());
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
summaryBetween++;
|
||||
const auto viewHeight = (*lastViewIt)->height();
|
||||
summaryHeight += viewHeight
|
||||
? viewHeight
|
||||
: (*lastViewIt)->resizeGetHeight(fallbackWidth);
|
||||
}
|
||||
const auto makedMessage = history->makeMessage(
|
||||
_session->data().nextLocalMessageId(),
|
||||
entryIt->sponsored.from,
|
||||
entryIt->sponsored.textWithEntities,
|
||||
(*lastViewIt)->data());
|
||||
entryIt->item.reset(makedMessage.get());
|
||||
history->addNewInTheMiddle(
|
||||
makedMessage.get(),
|
||||
std::distance(begin(history->blocks), blockIt),
|
||||
std::distance(begin(messages()), lastViewIt) + 1);
|
||||
messages().back().get()->setPendingResize();
|
||||
list.injectedCount++;
|
||||
}
|
||||
}
|
||||
|
||||
bool SponsoredMessages::canHaveFor(not_null<History*> history) const {
|
||||
return history->peer->isChannel();
|
||||
}
|
||||
|
||||
void SponsoredMessages::request(not_null<History*> history) {
|
||||
void SponsoredMessages::request(not_null<History*> history, Fn<void()> done) {
|
||||
if (!canHaveFor(history)) {
|
||||
return;
|
||||
}
|
||||
|
@ -113,6 +204,9 @@ void SponsoredMessages::request(not_null<History*> history) {
|
|||
channel->inputChannel)
|
||||
).done([=](const MTPmessages_sponsoredMessages &result) {
|
||||
parse(history, result);
|
||||
if (done) {
|
||||
done();
|
||||
}
|
||||
}).fail([=] {
|
||||
_requests.remove(history);
|
||||
}).send();
|
||||
|
@ -138,7 +232,12 @@ void SponsoredMessages::parse(
|
|||
list.received = crl::now();
|
||||
for (const auto &message : messages) {
|
||||
append(history, list, message);
|
||||
break;
|
||||
}
|
||||
if (const auto postsBetween = data.vposts_between()) {
|
||||
list.postsBetween = postsBetween->v;
|
||||
list.state = State::InjectToMiddle;
|
||||
} else {
|
||||
list.state = State::AppendToEnd;
|
||||
}
|
||||
}, [](const MTPDmessages_sponsoredMessagesEmpty &) {
|
||||
});
|
||||
|
@ -240,6 +339,7 @@ void SponsoredMessages::clearItems(not_null<History*> history) {
|
|||
entry.item.reset();
|
||||
}
|
||||
list.showedAll = false;
|
||||
list.injectedCount = 0;
|
||||
}
|
||||
|
||||
const SponsoredMessages::Entry *SponsoredMessages::find(
|
||||
|
@ -301,4 +401,10 @@ SponsoredMessages::Details SponsoredMessages::lookupDetails(
|
|||
};
|
||||
}
|
||||
|
||||
SponsoredMessages::State SponsoredMessages::state(
|
||||
not_null<History*> history) const {
|
||||
const auto it = _data.find(history);
|
||||
return (it == end(_data)) ? State::None : it->second.state;
|
||||
}
|
||||
|
||||
} // namespace Data
|
||||
|
|
|
@ -46,6 +46,11 @@ struct SponsoredMessage {
|
|||
|
||||
class SponsoredMessages final {
|
||||
public:
|
||||
enum class State {
|
||||
None,
|
||||
AppendToEnd,
|
||||
InjectToMiddle,
|
||||
};
|
||||
struct Details {
|
||||
std::optional<QString> hash;
|
||||
PeerData *peer = nullptr;
|
||||
|
@ -58,13 +63,21 @@ public:
|
|||
~SponsoredMessages();
|
||||
|
||||
[[nodiscard]] bool canHaveFor(not_null<History*> history) const;
|
||||
void request(not_null<History*> history);
|
||||
[[nodiscard]] bool append(not_null<History*> history);
|
||||
void request(not_null<History*> history, Fn<void()> done);
|
||||
void clearItems(not_null<History*> history);
|
||||
[[nodiscard]] Details lookupDetails(const FullMsgId &fullId) const;
|
||||
|
||||
[[nodiscard]] bool append(not_null<History*> history);
|
||||
void inject(
|
||||
not_null<History*> history,
|
||||
MsgId injectAfterMsgId,
|
||||
int betweenHeight,
|
||||
int fallbackWidth);
|
||||
|
||||
void view(const FullMsgId &fullId);
|
||||
|
||||
[[nodiscard]] State state(not_null<History*> history) const;
|
||||
|
||||
private:
|
||||
using OwnedItem = std::unique_ptr<HistoryItem, HistoryItem::Destroyer>;
|
||||
struct Entry {
|
||||
|
@ -73,8 +86,13 @@ private:
|
|||
};
|
||||
struct List {
|
||||
std::vector<Entry> entries;
|
||||
// Data between history displays.
|
||||
size_t injectedCount = 0;
|
||||
bool showedAll = false;
|
||||
//
|
||||
crl::time received = 0;
|
||||
int postsBetween = 0;
|
||||
State state = State::None;
|
||||
};
|
||||
struct Request {
|
||||
mtpRequestId requestId = 0;
|
||||
|
|
|
@ -764,7 +764,8 @@ not_null<HistoryItem*> History::addNewLocalMessage(
|
|||
makeMessage(
|
||||
id,
|
||||
from,
|
||||
textWithEntities),
|
||||
textWithEntities,
|
||||
nullptr),
|
||||
true);
|
||||
}
|
||||
|
||||
|
|
|
@ -34,6 +34,7 @@ class Session;
|
|||
class Folder;
|
||||
class ChatFilter;
|
||||
struct SponsoredFrom;
|
||||
class SponsoredMessages;
|
||||
|
||||
enum class ForwardOptions {
|
||||
PreserveInfo,
|
||||
|
@ -495,6 +496,8 @@ private:
|
|||
not_null<HistoryItem*> addNewToBack(
|
||||
not_null<HistoryItem*> item,
|
||||
bool unread);
|
||||
|
||||
friend class Data::SponsoredMessages;
|
||||
not_null<HistoryItem*> addNewInTheMiddle(
|
||||
not_null<HistoryItem*> item,
|
||||
int blockIndex,
|
||||
|
|
|
@ -636,14 +636,17 @@ HistoryMessage::HistoryMessage(
|
|||
not_null<History*> history,
|
||||
MsgId id,
|
||||
Data::SponsoredFrom from,
|
||||
const TextWithEntities &textWithEntities)
|
||||
const TextWithEntities &textWithEntities,
|
||||
HistoryItem *injectedAfter)
|
||||
: HistoryItem(
|
||||
history,
|
||||
id,
|
||||
((history->peer->isChannel() ? MessageFlag::Post : MessageFlag(0))
|
||||
//| (from.peer ? MessageFlag::HasFromId : MessageFlag(0))
|
||||
| MessageFlag::Local),
|
||||
HistoryItem::NewMessageDate(0),
|
||||
HistoryItem::NewMessageDate(injectedAfter
|
||||
? injectedAfter->date()
|
||||
: 0),
|
||||
/*from.peer ? from.peer->id : */PeerId(0)) {
|
||||
createComponentsHelper(
|
||||
_flags,
|
||||
|
|
|
@ -130,7 +130,8 @@ public:
|
|||
not_null<History*> history,
|
||||
MsgId id,
|
||||
Data::SponsoredFrom from,
|
||||
const TextWithEntities &textWithEntities); // sponsored
|
||||
const TextWithEntities &textWithEntities,
|
||||
HistoryItem *injectedAfter); // sponsored
|
||||
|
||||
void refreshMedia(const MTPMessageMedia *media);
|
||||
void refreshSentMedia(const MTPMessageMedia *media);
|
||||
|
|
|
@ -2288,9 +2288,25 @@ void HistoryWidget::showHistory(
|
|||
showAboutTopPromotion();
|
||||
|
||||
{
|
||||
auto &sponsored = session().data().sponsoredMessages();
|
||||
sponsored.request(_history);
|
||||
_scroll->setTrackingContent(sponsored.canHaveFor(_history));
|
||||
_scroll->setTrackingContent(false);
|
||||
const auto checkState = crl::guard(this, [=] {
|
||||
auto &sponsored = session().data().sponsoredMessages();
|
||||
using State = Data::SponsoredMessages::State;
|
||||
const auto state = sponsored.state(_history);
|
||||
if (state == State::AppendToEnd) {
|
||||
_scroll->setTrackingContent(
|
||||
sponsored.canHaveFor(_history));
|
||||
} else if (state == State::InjectToMiddle) {
|
||||
if (_list) {
|
||||
_list->setCanHaveFromUserpicsSponsored(true);
|
||||
}
|
||||
injectSponsoredMessages();
|
||||
}
|
||||
});
|
||||
session().data().sponsoredMessages().request(
|
||||
_history,
|
||||
checkState);
|
||||
checkState();
|
||||
}
|
||||
} else {
|
||||
_chooseForReport = nullptr;
|
||||
|
@ -2354,6 +2370,14 @@ void HistoryWidget::setHistory(History *history) {
|
|||
refreshAttachBotsMenu();
|
||||
}
|
||||
|
||||
void HistoryWidget::injectSponsoredMessages() const {
|
||||
session().data().sponsoredMessages().inject(
|
||||
_history,
|
||||
_showAtMsgId,
|
||||
_scroll->height() * 2,
|
||||
_scroll->width());
|
||||
}
|
||||
|
||||
void HistoryWidget::refreshAttachBotsMenu() {
|
||||
_attachBotsMenu = nullptr;
|
||||
if (!_history) {
|
||||
|
@ -3268,7 +3292,7 @@ void HistoryWidget::loadMessagesDown() {
|
|||
auto loadMigrated = _migrated && !(_migrated->isEmpty() || _migrated->loadedAtBottom() || (!_history->isEmpty() && !_history->loadedAtTop()));
|
||||
auto from = loadMigrated ? _migrated : _history;
|
||||
if (from->loadedAtBottom()) {
|
||||
session().data().sponsoredMessages().request(_history);
|
||||
session().data().sponsoredMessages().request(_history, nullptr);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -5659,6 +5683,7 @@ void HistoryWidget::addMessagesToBack(
|
|||
if (!_firstLoadRequest) {
|
||||
updateHistoryGeometry(false, true, { ScrollChangeNoJumpToBottom, 0 });
|
||||
}
|
||||
injectSponsoredMessages();
|
||||
}
|
||||
|
||||
void HistoryWidget::updateBotKeyboard(History *h, bool force) {
|
||||
|
|
|
@ -604,6 +604,8 @@ private:
|
|||
void refreshSendAsToggle();
|
||||
void refreshAttachBotsMenu();
|
||||
|
||||
void injectSponsoredMessages() const;
|
||||
|
||||
bool kbWasHidden() const;
|
||||
|
||||
void searchInChat();
|
||||
|
|
Loading…
Add table
Reference in a new issue