Jump to near reply inside a replies thread.
This commit is contained in:
parent
f8b83dd186
commit
1849f01b15
8 changed files with 89 additions and 71 deletions
|
@ -102,10 +102,10 @@ bool RepliesList::buildFromData(not_null<Viewer*> viewer) {
|
|||
const auto i = around
|
||||
? ranges::lower_bound(_list, around, std::greater<>())
|
||||
: end(_list);
|
||||
const auto availableBefore = (i - begin(_list));
|
||||
const auto availableAfter = (end(_list) - i);
|
||||
const auto useBefore = std::min(availableBefore, viewer->limitBefore);
|
||||
const auto useAfter = std::min(availableAfter, viewer->limitAfter + 1);
|
||||
const auto availableBefore = (end(_list) - i);
|
||||
const auto availableAfter = (i - begin(_list));
|
||||
const auto useBefore = std::min(availableBefore, viewer->limitBefore + 1);
|
||||
const auto useAfter = std::min(availableAfter, viewer->limitAfter);
|
||||
const auto slice = &viewer->slice;
|
||||
if (_skippedBefore.has_value()) {
|
||||
slice->skippedBefore
|
||||
|
@ -115,20 +115,23 @@ bool RepliesList::buildFromData(not_null<Viewer*> viewer) {
|
|||
slice->skippedAfter
|
||||
= (*_skippedAfter + (availableAfter - useAfter));
|
||||
}
|
||||
|
||||
const auto channelId = _history->channelId();
|
||||
slice->ids.clear();
|
||||
slice->ids.reserve(useBefore + useAfter);
|
||||
for (auto j = i - useBefore, e = i + useAfter; j != e; ++j) {
|
||||
slice->ids.reserve(useAfter + useBefore);
|
||||
for (auto j = i - useAfter, e = i + useBefore; j != e; ++j) {
|
||||
slice->ids.emplace_back(channelId, *j);
|
||||
}
|
||||
ranges::reverse(slice->ids);
|
||||
|
||||
slice->fullCount = _fullCount.current();
|
||||
if (_skippedBefore != 0 && useBefore < viewer->limitBefore) {
|
||||
if (_skippedBefore != 0 && useBefore < viewer->limitBefore + 1) {
|
||||
loadBefore();
|
||||
}
|
||||
if (_skippedAfter != 0 && useAfter < viewer->limitAfter + 1) {
|
||||
if (_skippedAfter != 0 && useAfter < viewer->limitAfter) {
|
||||
loadAfter();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -365,6 +368,11 @@ bool RepliesList::processMessagesIsEmpty(const MTPmessages_Messages &result) {
|
|||
refreshed.insert(refreshed.end(), _list.begin(), _list.end());
|
||||
_list = std::move(refreshed);
|
||||
}
|
||||
if (_fullCount.current() && _skippedBefore && !_skippedAfter) {
|
||||
_skippedAfter = *_fullCount.current() - *_skippedBefore - _list.size();
|
||||
} else if (_fullCount.current() && _skippedAfter && !_skippedBefore) {
|
||||
_skippedBefore = *_fullCount.current() - *_skippedAfter - _list.size();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -929,15 +929,13 @@ ClickHandlerPtr goToMessageClickHandler(
|
|||
return std::make_shared<LambdaClickHandler>([=] {
|
||||
if (const auto main = App::main()) { // multi good
|
||||
if (&main->session() == &peer->session()) {
|
||||
if (const auto returnTo = peer->owner().message(returnToId)) {
|
||||
if (returnTo->history()->peer == peer) {
|
||||
main->pushReplyReturn(returnTo);
|
||||
}
|
||||
}
|
||||
main->controller()->showPeerHistory(
|
||||
peer,
|
||||
Window::SectionShow::Way::Forward,
|
||||
msgId);
|
||||
auto params = Window::SectionShow{
|
||||
Window::SectionShow::Way::Forward
|
||||
};
|
||||
params.origin = Window::SectionShow::OriginMessage{
|
||||
returnToId
|
||||
};
|
||||
main->controller()->showPeerHistory(peer, params, msgId);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
|
@ -930,6 +930,26 @@ std::unique_ptr<Window::SectionMemento> RepliesWidget::createMemento() {
|
|||
return result;
|
||||
}
|
||||
|
||||
bool RepliesWidget::showMessage(
|
||||
PeerId peerId,
|
||||
const Window::SectionShow ¶ms,
|
||||
MsgId messageId) {
|
||||
if (peerId != _history->peer->id) {
|
||||
return false;
|
||||
}
|
||||
const auto id = FullMsgId{
|
||||
_history->channelId(),
|
||||
messageId
|
||||
};
|
||||
const auto message = _history->owner().message(id);
|
||||
if (!message || message->replyToTop() != _rootId) {
|
||||
return false;
|
||||
}
|
||||
_highlightMessageId = id;
|
||||
showAtPosition(Data::MessagePosition(message->date(), id));
|
||||
return true;
|
||||
}
|
||||
|
||||
void RepliesWidget::saveState(not_null<RepliesMemento*> memento) {
|
||||
memento->setReplies(_replies);
|
||||
_inner->saveState(memento->list());
|
||||
|
@ -1092,37 +1112,6 @@ rpl::producer<Data::MessagesSlice> RepliesWidget::listSource(
|
|||
return _replies->source(aroundId, limitBefore, limitAfter);
|
||||
}
|
||||
|
||||
void RepliesWidget::highlightSingleNewMessage(
|
||||
const Data::MessagesSlice &slice) {
|
||||
const auto guard = gsl::finally([&] { _lastSlice = slice; });
|
||||
if (_lastSlice.ids.empty()
|
||||
|| (slice.ids.size() != _lastSlice.ids.size() + 1)) {
|
||||
return;
|
||||
}
|
||||
auto firstDifferent = 0;
|
||||
while (firstDifferent != _lastSlice.ids.size()) {
|
||||
if (slice.ids[firstDifferent] != _lastSlice.ids[firstDifferent]) {
|
||||
break;
|
||||
}
|
||||
++firstDifferent;
|
||||
}
|
||||
auto lastDifferent = slice.ids.size() - 1;
|
||||
while (lastDifferent != firstDifferent) {
|
||||
if (slice.ids[lastDifferent] != _lastSlice.ids[lastDifferent - 1]) {
|
||||
break;
|
||||
}
|
||||
--lastDifferent;
|
||||
}
|
||||
if (firstDifferent != lastDifferent) {
|
||||
return;
|
||||
}
|
||||
const auto newId = slice.ids[firstDifferent];
|
||||
if (const auto item = session().data().message(newId)) {
|
||||
// _highlightMessageId = newId;
|
||||
showAtPosition(item->position());
|
||||
}
|
||||
}
|
||||
|
||||
bool RepliesWidget::listAllowsMultiSelect() {
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -80,6 +80,10 @@ public:
|
|||
not_null<Window::SectionMemento*> memento,
|
||||
const Window::SectionShow ¶ms) override;
|
||||
std::unique_ptr<Window::SectionMemento> createMemento() override;
|
||||
bool showMessage(
|
||||
PeerId peerId,
|
||||
const Window::SectionShow ¶ms,
|
||||
MsgId messageId) override;
|
||||
|
||||
void setInternalState(
|
||||
const QRect &geometry,
|
||||
|
@ -156,7 +160,6 @@ private:
|
|||
not_null<HistoryItem*> item,
|
||||
Api::SendOptions options,
|
||||
mtpRequestId *const saveEditMsgRequestId);
|
||||
void highlightSingleNewMessage(const Data::MessagesSlice &slice);
|
||||
void chooseAttach();
|
||||
[[nodiscard]] SendMenu::Type sendMenuType() const;
|
||||
|
||||
|
|
|
@ -1221,10 +1221,6 @@ Image *MainWidget::newBackgroundThumb() {
|
|||
: nullptr;
|
||||
}
|
||||
|
||||
void MainWidget::pushReplyReturn(not_null<HistoryItem*> item) {
|
||||
_history->pushReplyReturn(item);
|
||||
}
|
||||
|
||||
void MainWidget::setInnerFocus() {
|
||||
if (_hider || !_history->peer()) {
|
||||
if (!_hider && _mainSection) {
|
||||
|
@ -1381,6 +1377,20 @@ void MainWidget::ui_showPeerHistory(
|
|||
return;
|
||||
}
|
||||
}
|
||||
if (IsServerMsgId(showAtMsgId)
|
||||
&& _mainSection
|
||||
&& _mainSection->showMessage(peerId, params, showAtMsgId)) {
|
||||
return;
|
||||
}
|
||||
|
||||
using OriginMessage = SectionShow::OriginMessage;
|
||||
if (const auto origin = std::get_if<OriginMessage>(¶ms.origin)) {
|
||||
if (const auto returnTo = session().data().message(origin->id)) {
|
||||
if (returnTo->history()->peer->id == peerId) {
|
||||
_history->pushReplyReturn(returnTo);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_controller->dialogsListFocused().set(false, true);
|
||||
_a_dialogsWidth.stop();
|
||||
|
@ -2642,15 +2652,13 @@ void MainWidget::openPeerByName(
|
|||
}
|
||||
const auto returnToId = clickFromMessageId;
|
||||
InvokeQueued(this, [=] {
|
||||
if (const auto returnTo = session().data().message(returnToId)) {
|
||||
if (returnTo->history()->peer == peer) {
|
||||
pushReplyReturn(returnTo);
|
||||
}
|
||||
}
|
||||
_controller->showPeerHistory(
|
||||
peer->id,
|
||||
SectionShow::Way::Forward,
|
||||
msgId);
|
||||
auto params = SectionShow{
|
||||
SectionShow::Way::Forward
|
||||
};
|
||||
params.origin = SectionShow::OriginMessage{
|
||||
returnToId
|
||||
};
|
||||
_controller->showPeerHistory(peer->id, params, msgId);
|
||||
});
|
||||
}
|
||||
} else {
|
||||
|
|
|
@ -204,8 +204,6 @@ public:
|
|||
void checkChatBackground();
|
||||
Image *newBackgroundThumb();
|
||||
|
||||
void pushReplyReturn(not_null<HistoryItem*> item);
|
||||
|
||||
// Does offerPeer or showPeerHistory.
|
||||
void choosePeer(PeerId peerId, MsgId showAtMsgId);
|
||||
void clearBotStartToken(PeerData *peer);
|
||||
|
|
|
@ -40,20 +40,20 @@ class AbstractSectionWidget
|
|||
public:
|
||||
AbstractSectionWidget(
|
||||
QWidget *parent,
|
||||
not_null<Window::SessionController*> controller)
|
||||
not_null<SessionController*> controller)
|
||||
: RpWidget(parent)
|
||||
, _controller(controller) {
|
||||
}
|
||||
|
||||
[[nodiscard]] Main::Session &session() const;
|
||||
[[nodiscard]] not_null<Window::SessionController*> controller() const {
|
||||
[[nodiscard]] not_null<SessionController*> controller() const {
|
||||
return _controller;
|
||||
}
|
||||
|
||||
// Tabbed selector management.
|
||||
virtual bool pushTabbedSelectorToThirdSection(
|
||||
not_null<PeerData*> peer,
|
||||
const Window::SectionShow ¶ms) {
|
||||
const SectionShow ¶ms) {
|
||||
return false;
|
||||
}
|
||||
virtual bool returnTabbedSelector() {
|
||||
|
@ -61,7 +61,7 @@ public:
|
|||
}
|
||||
|
||||
private:
|
||||
const not_null<Window::SessionController*> _controller;
|
||||
const not_null<SessionController*> _controller;
|
||||
|
||||
};
|
||||
|
||||
|
@ -82,7 +82,7 @@ class SectionWidget : public AbstractSectionWidget {
|
|||
public:
|
||||
SectionWidget(
|
||||
QWidget *parent,
|
||||
not_null<Window::SessionController*> controller);
|
||||
not_null<SessionController*> controller);
|
||||
|
||||
virtual Dialogs::RowDescriptor activeChat() const {
|
||||
return {};
|
||||
|
@ -118,6 +118,13 @@ public:
|
|||
not_null<SectionMemento*> memento,
|
||||
const SectionShow ¶ms) = 0;
|
||||
|
||||
virtual bool showMessage(
|
||||
PeerId peerId,
|
||||
const SectionShow ¶ms,
|
||||
MsgId messageId) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Create a memento of that section to store it in the history stack.
|
||||
// This method may modify the section ("take" heavy items).
|
||||
virtual std::unique_ptr<SectionMemento> createMemento();
|
||||
|
@ -135,7 +142,7 @@ public:
|
|||
}
|
||||
|
||||
static void PaintBackground(
|
||||
not_null<Window::SessionController*> controller,
|
||||
not_null<SessionController*> controller,
|
||||
not_null<QWidget*> widget,
|
||||
QRect clip);
|
||||
|
||||
|
@ -150,7 +157,7 @@ protected:
|
|||
|
||||
// Called after the hideChildren() call in showAnimated().
|
||||
virtual void showAnimatedHook(
|
||||
const Window::SectionSlideParams ¶ms) {
|
||||
const SectionSlideParams ¶ms) {
|
||||
}
|
||||
|
||||
// Called after the showChildren() call in showFinished().
|
||||
|
|
|
@ -84,6 +84,12 @@ struct SectionShow {
|
|||
Backward,
|
||||
ClearStack,
|
||||
};
|
||||
|
||||
struct OriginMessage {
|
||||
FullMsgId id;
|
||||
};
|
||||
using Origin = std::variant<v::null_t, OriginMessage>;
|
||||
|
||||
SectionShow(
|
||||
Way way = Way::Forward,
|
||||
anim::type animated = anim::type::normal,
|
||||
|
@ -112,6 +118,7 @@ struct SectionShow {
|
|||
anim::type animated = anim::type::normal;
|
||||
anim::activation activation = anim::activation::normal;
|
||||
bool thirdColumn = false;
|
||||
Origin origin;
|
||||
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in a new issue