mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-06-05 06:33:57 +02:00
parent
f064692e57
commit
53ac4c00ad
4 changed files with 66 additions and 35 deletions
|
@ -42,7 +42,10 @@ struct RepliesList::Viewer {
|
||||||
MsgId around = 0;
|
MsgId around = 0;
|
||||||
int limitBefore = 0;
|
int limitBefore = 0;
|
||||||
int limitAfter = 0;
|
int limitAfter = 0;
|
||||||
|
int injectedForRoot = 0;
|
||||||
base::has_weak_ptr guard;
|
base::has_weak_ptr guard;
|
||||||
|
bool stale = true;
|
||||||
|
bool scheduled = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
RepliesList::RepliesList(not_null<History*> history, MsgId rootId)
|
RepliesList::RepliesList(not_null<History*> history, MsgId rootId)
|
||||||
|
@ -67,7 +70,9 @@ rpl::producer<MessagesSlice> RepliesList::source(
|
||||||
_history->session().changes().historyFlagsValue(
|
_history->session().changes().historyFlagsValue(
|
||||||
_history,
|
_history,
|
||||||
Data::HistoryUpdate::Flag::LocalMessages)
|
Data::HistoryUpdate::Flag::LocalMessages)
|
||||||
) | rpl::map([=](MessagesSlice &&server, const auto &) {
|
) | rpl::filter([=](const MessagesSlice &data, const auto &) {
|
||||||
|
return (data.fullCount.value_or(0) >= 0);
|
||||||
|
}) | rpl::map([=](MessagesSlice &&server, const auto &) {
|
||||||
appendLocalMessages(server);
|
appendLocalMessages(server);
|
||||||
return std::move(server);
|
return std::move(server);
|
||||||
});
|
});
|
||||||
|
@ -82,10 +87,22 @@ rpl::producer<MessagesSlice> RepliesList::sourceFromServer(
|
||||||
auto lifetime = rpl::lifetime();
|
auto lifetime = rpl::lifetime();
|
||||||
const auto viewer = lifetime.make_state<Viewer>();
|
const auto viewer = lifetime.make_state<Viewer>();
|
||||||
const auto push = [=] {
|
const auto push = [=] {
|
||||||
|
viewer->scheduled = false;
|
||||||
if (buildFromData(viewer)) {
|
if (buildFromData(viewer)) {
|
||||||
|
viewer->stale = false;
|
||||||
consumer.put_next_copy(viewer->slice);
|
consumer.put_next_copy(viewer->slice);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
const auto pushDelayed = [=] {
|
||||||
|
if (!viewer->stale) {
|
||||||
|
viewer->stale = true;
|
||||||
|
consumer.put_next_copy(MessagesSlice{ .fullCount = -1 });
|
||||||
|
}
|
||||||
|
if (!viewer->scheduled) {
|
||||||
|
viewer->scheduled = true;
|
||||||
|
crl::on_main(&viewer->guard, push);
|
||||||
|
}
|
||||||
|
};
|
||||||
viewer->around = around;
|
viewer->around = around;
|
||||||
viewer->limitBefore = limitBefore;
|
viewer->limitBefore = limitBefore;
|
||||||
viewer->limitAfter = limitAfter;
|
viewer->limitAfter = limitAfter;
|
||||||
|
@ -96,14 +113,10 @@ rpl::producer<MessagesSlice> RepliesList::sourceFromServer(
|
||||||
| MessageUpdate::Flag::Destroyed
|
| MessageUpdate::Flag::Destroyed
|
||||||
) | rpl::filter([=](const MessageUpdate &update) {
|
) | rpl::filter([=](const MessageUpdate &update) {
|
||||||
return applyUpdate(viewer, update);
|
return applyUpdate(viewer, update);
|
||||||
}) | rpl::start_with_next([=] {
|
}) | rpl::start_with_next(pushDelayed, lifetime);
|
||||||
crl::on_main(&viewer->guard, push);
|
|
||||||
}, lifetime);
|
|
||||||
|
|
||||||
_partLoaded.events(
|
_partLoaded.events(
|
||||||
) | rpl::start_with_next([=] {
|
) | rpl::start_with_next(pushDelayed, lifetime);
|
||||||
crl::on_main(&viewer->guard, push);
|
|
||||||
}, lifetime);
|
|
||||||
|
|
||||||
push();
|
push();
|
||||||
return lifetime;
|
return lifetime;
|
||||||
|
@ -173,32 +186,37 @@ rpl::producer<int> RepliesList::fullCount() const {
|
||||||
return _fullCount.value() | rpl::filter_optional();
|
return _fullCount.value() | rpl::filter_optional();
|
||||||
}
|
}
|
||||||
|
|
||||||
void RepliesList::injectRootMessageAndReverse(
|
void RepliesList::injectRootMessageAndReverse(not_null<Viewer*> viewer) {
|
||||||
not_null<MessagesSlice*> slice) {
|
injectRootMessage(viewer);
|
||||||
injectRootMessage(slice);
|
ranges::reverse(viewer->slice.ids);
|
||||||
ranges::reverse(slice->ids);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void RepliesList::injectRootMessage(not_null<MessagesSlice*> slice) {
|
void RepliesList::injectRootMessage(not_null<Viewer*> viewer) {
|
||||||
|
const auto slice = &viewer->slice;
|
||||||
|
viewer->injectedForRoot = 0;
|
||||||
if (slice->skippedBefore != 0) {
|
if (slice->skippedBefore != 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (const auto root = lookupRoot()) {
|
const auto root = lookupRoot();
|
||||||
injectRootDivider(root, slice);
|
if (!root) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
injectRootDivider(root, slice);
|
||||||
|
|
||||||
if (const auto group = _history->owner().groups().find(root)) {
|
if (const auto group = _history->owner().groups().find(root)) {
|
||||||
for (const auto item : ranges::view::reverse(group->items)) {
|
for (const auto item : ranges::view::reverse(group->items)) {
|
||||||
slice->ids.push_back(item->fullId());
|
slice->ids.push_back(item->fullId());
|
||||||
}
|
|
||||||
if (slice->fullCount) {
|
|
||||||
*slice->fullCount += group->items.size();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
slice->ids.push_back(root->fullId());
|
|
||||||
if (slice->fullCount) {
|
|
||||||
++*slice->fullCount;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
viewer->injectedForRoot = group->items.size();
|
||||||
|
if (slice->fullCount) {
|
||||||
|
*slice->fullCount += group->items.size();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
slice->ids.push_back(root->fullId());
|
||||||
|
viewer->injectedForRoot = 1;
|
||||||
|
}
|
||||||
|
if (slice->fullCount) {
|
||||||
|
*slice->fullCount += viewer->injectedForRoot;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -232,7 +250,8 @@ bool RepliesList::buildFromData(not_null<Viewer*> viewer) {
|
||||||
= viewer->slice.skippedBefore
|
= viewer->slice.skippedBefore
|
||||||
= viewer->slice.skippedAfter
|
= viewer->slice.skippedAfter
|
||||||
= 0;
|
= 0;
|
||||||
injectRootMessageAndReverse(&viewer->slice);
|
viewer->injectedForRoot = 0;
|
||||||
|
injectRootMessageAndReverse(viewer);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
const auto around = [&] {
|
const auto around = [&] {
|
||||||
|
@ -285,7 +304,7 @@ bool RepliesList::buildFromData(not_null<Viewer*> viewer) {
|
||||||
slice->ids.empty() ? 0 : slice->ids.back().msg));
|
slice->ids.empty() ? 0 : slice->ids.back().msg));
|
||||||
slice->fullCount = _fullCount.current();
|
slice->fullCount = _fullCount.current();
|
||||||
|
|
||||||
injectRootMessageAndReverse(slice);
|
injectRootMessageAndReverse(viewer);
|
||||||
|
|
||||||
if (_skippedBefore != 0 && useBefore < viewer->limitBefore + 1) {
|
if (_skippedBefore != 0 && useBefore < viewer->limitBefore + 1) {
|
||||||
loadBefore();
|
loadBefore();
|
||||||
|
@ -301,10 +320,20 @@ bool RepliesList::applyUpdate(
|
||||||
not_null<Viewer*> viewer,
|
not_null<Viewer*> viewer,
|
||||||
const MessageUpdate &update) {
|
const MessageUpdate &update) {
|
||||||
if (update.item->history() != _history
|
if (update.item->history() != _history
|
||||||
|| update.item->replyToTop() != _rootId
|
|
||||||
|| !IsServerMsgId(update.item->id)) {
|
|| !IsServerMsgId(update.item->id)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
if (update.flags & MessageUpdate::Flag::Destroyed) {
|
||||||
|
const auto id = update.item->fullId();
|
||||||
|
for (auto i = 0; i != viewer->injectedForRoot; ++i) {
|
||||||
|
if (viewer->slice.ids[i] == id) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (update.item->replyToTop() != _rootId) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
const auto id = update.item->id;
|
const auto id = update.item->id;
|
||||||
const auto i = ranges::lower_bound(_list, id, std::greater<>());
|
const auto i = ranges::lower_bound(_list, id, std::greater<>());
|
||||||
if (update.flags & MessageUpdate::Flag::Destroyed) {
|
if (update.flags & MessageUpdate::Flag::Destroyed) {
|
||||||
|
|
|
@ -47,8 +47,8 @@ private:
|
||||||
[[nodiscard]] bool applyUpdate(
|
[[nodiscard]] bool applyUpdate(
|
||||||
not_null<Viewer*> viewer,
|
not_null<Viewer*> viewer,
|
||||||
const MessageUpdate &update);
|
const MessageUpdate &update);
|
||||||
void injectRootMessageAndReverse(not_null<MessagesSlice*> slice);
|
void injectRootMessageAndReverse(not_null<Viewer*> viewer);
|
||||||
void injectRootMessage(not_null<MessagesSlice*> slice);
|
void injectRootMessage(not_null<Viewer*> viewer);
|
||||||
void injectRootDivider(
|
void injectRootDivider(
|
||||||
not_null<HistoryItem*> root,
|
not_null<HistoryItem*> root,
|
||||||
not_null<MessagesSlice*> slice);
|
not_null<MessagesSlice*> slice);
|
||||||
|
|
|
@ -292,9 +292,10 @@ ListWidget::ListWidget(
|
||||||
}, lifetime());
|
}, lifetime());
|
||||||
|
|
||||||
session().data().itemRemoved(
|
session().data().itemRemoved(
|
||||||
) | rpl::start_with_next(
|
) | rpl::start_with_next([=](not_null<const HistoryItem*> item) {
|
||||||
[this](auto item) { itemRemoved(item); },
|
itemRemoved(item);
|
||||||
lifetime());
|
}, lifetime());
|
||||||
|
|
||||||
subscribe(session().data().queryItemVisibility(), [this](const Data::Session::ItemVisibilityQuery &query) {
|
subscribe(session().data().queryItemVisibility(), [this](const Data::Session::ItemVisibilityQuery &query) {
|
||||||
if (const auto view = viewForItem(query.item)) {
|
if (const auto view = viewForItem(query.item)) {
|
||||||
const auto top = itemTop(view);
|
const auto top = itemTop(view);
|
||||||
|
|
|
@ -216,6 +216,7 @@ RepliesWidget::RepliesWidget(
|
||||||
if (update.item == _root) {
|
if (update.item == _root) {
|
||||||
_root = nullptr;
|
_root = nullptr;
|
||||||
updatePinnedVisibility();
|
updatePinnedVisibility();
|
||||||
|
controller->showBackFromStack();
|
||||||
}
|
}
|
||||||
while (update.item == _replyReturn) {
|
while (update.item == _replyReturn) {
|
||||||
calculateNextReplyReturn();
|
calculateNextReplyReturn();
|
||||||
|
@ -1758,7 +1759,7 @@ MessagesBarData RepliesWidget::listMessagesBar(
|
||||||
for (auto i = 0, count = int(elements.size()); i != count; ++i) {
|
for (auto i = 0, count = int(elements.size()); i != count; ++i) {
|
||||||
const auto item = elements[i]->data();
|
const auto item = elements[i]->data();
|
||||||
if (IsServerMsgId(item->id) && item->id > till) {
|
if (IsServerMsgId(item->id) && item->id > till) {
|
||||||
if (item->out()) {
|
if (item->out() || !item->replyToId()) {
|
||||||
readTill(item);
|
readTill(item);
|
||||||
} else {
|
} else {
|
||||||
return MessagesBarData{
|
return MessagesBarData{
|
||||||
|
|
Loading…
Add table
Reference in a new issue